Bài tập về vòng lặp

Liên hệ QC

ndu96081631

Huyền thoại GPE
Thành viên BQT
Super Moderator
Tham gia
5/6/08
Bài viết
30,703
Được thích
53,946
Những ai đã từng xem qua bài viết này: Giới thiệu Cơ bản về vòng lặp For . . . next của sư phụ ptm0412 giờ hãy cùng làm 1 vài bài tập từ đơn giản đến nâng cao nhé
Xin mở màn bằng 1 bài tập sau:

Bài tập 01:

Hãy tính xem từ năm 1900 đến nay có bao nhiêu ngày thuộc dạng THỨ SÁU NGÀY 13
------------------------
Các bạn ai có bài tập gì hay xin post lên đây nhé! Cảm ơn
 
Chỉnh sửa lần cuối bởi điều hành viên:
Câu c, nếu tô 1 màu, thì căn cứ vào diễn giải của RollOver, và đoạn code sau:

PHP:
    For iValue = 1 To iCols * iRows
        iRow = (iValue - 1) \ iCols + 1
        iCol = (iValue - 1) Mod iCols + 1
        If ((iRow + iCol) Mod 2 = 0) Then objDic.Add iValue, iValue
    Next

Nếu thay điều kiện If (iRow + iCol) Mod 2 = 0 thành
If (iRow + iCol) Mod 2 = 1
sẽ tô các ô còn lại.

Vậy cho code chạy 2 lần với 2 tham số sẽ tô bàn cờ 2 màu:

Mã:
Private Sub CommandButton1_Click()
    Cells.Clear
    iCols = InputBox("Nhap so cot:")
    iRows = InputBox("Nhap so dong:")

Caro1 iCols, iRows, 1, 15
Caro1 iCols, iRows, 0, 16
End Sub

Mã:
Sub Caro1(ByVal iCols As Long, ByVal iRows As Long, le As Long, clor As Long)
    Dim iValue As Long, iCol As Long, iRow As Long
    Dim objDic As New Dictionary, EpRow As Long, EpCol As Long
    For iValue = 1 To iCols * iRows
        iRow = (iValue - 1) \ iCols + 1
        iCol = (iValue - 1) Mod iCols + 1
        If ((iRow + iCol) Mod 2 = [COLOR="Red"][B]le[/B][/COLOR]) Then objDic.Add iValue, iValue
    Next

Đoạn dưới giữ nguyên chỉ sửa 2 dòng sau:
Mã:
....
        Cells(iRow, iCol).Interior.ColorIndex = [B][COLOR="Red"]clor[/COLOR][/B]
...
 
Lần chỉnh sửa cuối:
Upvote 0
Tiếp tục đi các Anh. Cho Em út có cơ hội học hỏi với. Các Bạn nào trên diễn đàn đang tham gia học hỏi topic này thì cố viết code đưa lên để các Anh giúp cho, đừng sợ sai gì cả đâu có ai mới học lại giỏi liền đâu? Riêng Em cái vụ VBA này rất khoái (mặc dù ít áp dụng cho công việc của mình).
 
Upvote 0
Tiếp tục đi các Anh. Cho Em út có cơ hội học hỏi với. Các Bạn nào trên diễn đàn đang tham gia học hỏi topic này thì cố viết code đưa lên để các Anh giúp cho, đừng sợ sai gì cả đâu có ai mới học lại giỏi liền đâu? Riêng Em cái vụ VBA này rất khoái (mặc dù ít áp dụng cho công việc của mình).

Ngoài việc "chờ" người ta đưa bài tập mẫu, các bạn có thể tự mình nghĩ ra 1 tình huống gì đó phải dùng đến vòng lập rồi đưa lên đây để chúng ta cùng "mổ xẻ"
Nhớ lại ngày trước, khi mới chập chững vấn thân vào VBA, tay cơ còn quá non mà tôi còn dám "gan cùng mình", mở nguyên 1 topic ĐỐ VUI VỀ VBA đấy thôi
Ngán gì chứ? Hi... hi...
 
Upvote 0
Tiếp tục đi các Anh. Cho Em út có cơ hội học hỏi với. Các Bạn nào trên diễn đàn đang tham gia học hỏi topic này thì cố viết code đưa lên để các Anh giúp cho, đừng sợ sai gì cả đâu có ai mới học lại giỏi liền đâu? Riêng Em cái vụ VBA này rất khoái (mặc dù ít áp dụng cho công việc của mình).
Thêm bài số 05 tương tự loạt bài 04 như sau:
Câu a: Tô màu với N bất kỳ theo nguyên tắc như sau:
attachment.php

Câu b: Tương tự câu a nhưng theo nguyên tắc:
attachment.php

Chú ý là tô theo thứ tự các con số của mỗi ô.
 

File đính kèm

  • 123.GIF
    123.GIF
    5.3 KB · Đọc: 106
  • 456.GIF
    456.GIF
    5.6 KB · Đọc: 106
Upvote 0
Gợi ý sơ qua!
Với câu 5a) của rollover79, các bạn dùng 2 vòng lập là dễ nhất:
PHP:
For iR = 1 To n
    For iC = n - iR + 1 To n + iR - 1
Với
- n là số các bạn nhập vào InputBox
- iRiC là vị trí cell
- Cells(iR, iC) chính là cell mà các bạn cần tô màu
Gợi ý gần như... toàn bộ rồi đấy!
-----------
Cũng có thể dùng 1 vòng lập For i = 1 to n^2 ---> Tùy ý
Thử xem! Câu 5b) gần như tương tự (về cách suy luận)
 
Lần chỉnh sửa cuối:
Upvote 0
Em xin đáp án 2 câu trên bằng 2 vòng lặp For như anh NDU gợi ý như sau:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Câu a:
Mã:
Sub Tomau1()
Dim iR As Long, iC As Long, N As Long
  Cells.Clear
  N = InputBox("Hay nhap N?")
 For iR = 1 To N
   For iC = N - iR + 1 To N + iR - 1
      With Cells(iR, iC)
        .Interior.ColorIndex = 5
        Sleep 50
      End With
    Next iC
 Next iR
End Sub
Câu b:
Mã:
Sub Tomau2()
Dim iR As Long, iC As Long, N As Long
  Cells.Clear
  N = InputBox("Hay nhap N?")
 For iR = 1 To N
   For iC = N - iR + 1 To N + iR
      With Cells(iR, iC)
        .Interior.ColorIndex = 5
        Sleep 50
      End With
    Next iC
 Next iR
End Sub
Dùng 1 vòng lặp thì Em chưa nghiên cứu tới. Cố gắng chiều nay có thể hoàn thành 1 vòng lặp. Hì hì
 

File đính kèm

  • Taptomau.xls
    28.5 KB · Đọc: 17
Upvote 0
Dùng 1 vòng lặp thì Em chưa nghiên cứu tới. Cố gắng chiều nay có thể hoàn thành 1 vòng lặp. Hì hì
MinhCong khá lắm, nhất là đã tự mình suy luận được câu 5b) ---> Cố gắng lên, chẳng bao lâu bạn sẽ thành cao thủ như ai!
Sư phụ ptm0412 đã từng cho tôi 1 bài học: Cái khó nằm ở tư duy logic chứ còn code kiết gì đó chỉ là công cụ hổ trợ, làm vài lần tự nhiên quen tay thôi
Về vụ 1 vòng lập, nghiên cứu thì cứ việc nhưng xin lưu ý với bạn rằng với bài này, dù là 1 vòng lập hay 2 vòng lập thì tốc độ vẫn như nhau
(có chăng là nghiên cứu thuật toán chơi, biết đâu dùng trong dịp khác)
 
Lần chỉnh sửa cuối:
Upvote 0
MinhCong khá lắm, nhất là đã tự mình suy luận được câu 5b) ---> Cố gắng lên, chẳng bao lâu bạn sẽ thành cao thủ như ai!
Sư phụ ptm0412 đã từng cho tôi 1 bài học: Cái khó nằm ở tư duy logic chứ còn code kiết gì đó chỉ là công cụ hổ trợ, làm vài lần tự nhiên quen tay thôi
Về vụ 1 vòng lập, nghiên cứu thì cứ việc nhưng xin lưu ý với bạn rằng với bài này, dù là 1 vòng lập hay 2 vòng lập thì tốc độ vẫn như nhau
(có chăng là nghiên cứu thuật toán chơi, biết đâu dùng trong dịp khác)
1 vòng lặp Em làm có lẽ được 1/2 vì Em nghĩ đặt được điều kiện cho iRow rồi, còn cái ICol thì đang nghiên cứu, thấy khó tư duy quá. Biết cách nó chạy nhưng cái thuật toán thì chưa tìm ra được mới tức chứ.
Mã:
For i = 1 To N ^ 2
        iRow = IIf(i <= N, i, N)
iRow Em dò lại thì có lẽ là đúng (chưa chắc lắm).
 
Upvote 0
1 vòng lặp Em làm có lẽ được 1/2 vì Em nghĩ đặt được điều kiện cho iRow rồi, còn cái ICol thì đang nghiên cứu, thấy khó tư duy quá. Biết cách nó chạy nhưng cái thuật toán thì chưa tìm ra được mới tức chứ.
Mã:
For i = 1 To N ^ 2
        iRow = IIf(i <= N, i, N)
iRow Em dò lại thì có lẽ là đúng (chưa chắc lắm).
Hình như iRow bằng vầy thì phải
iRow = Int(Sqr(i - 1)) + 1
Kiểm tra lại xem ---> Khỏi IF
Khó ở chổ tìm iCol đấy ---> Bùn lắm thì IF... IF gì đó đi!
Ẹc... Ẹc...
 
Upvote 0
Vụ dùng 1 vòng lặp thì tốt nhất hãy nghĩ đến dùng gia số dòng cột có điều kiện. If iếc đâu có mất mát gì đâu.

Note: irow tính theo ndu mới đúng, MinhCong tính sai rồi.
 
Upvote 0
1 vòng lặp Em làm có lẽ được 1/2 vì Em nghĩ đặt được điều kiện cho iRow rồi, còn cái ICol thì đang nghiên cứu, thấy khó tư duy quá. Biết cách nó chạy nhưng cái thuật toán thì chưa tìm ra được mới tức chứ.
Mã:
For i = 1 To N ^ 2
        iRow = IIf(i <= N, i, N)
iRow Em dò lại thì có lẽ là đúng (chưa chắc lắm).
iRow thì như bác cách của bác ndu. iCol thì tôi gợi ý chút thế này.
Với mỗi 1 giá trị i ta đã biết iRow, với mỗi iRow ta đã biết cột xuất phát của dòng rồi, lấy cột xuất phát + thứ tự của ô tương ứng với giá trị i trong dòng đó là xong. Để tính thứ tự của ô tương ứng với giá trị i thì hãy thử vận dụng các dữ kiện bao gồm i và tổng số ô của các dòng phía trên xem sao.
Ví dụ:
Với N=4, khi i=8 ta có iRow=3, Cột xuất phát là cột 2(N-iRow+1), giờ ta tính tổng các ô của các dòng phía trên(dòng 1 và dòng 2), ở đây là 4=(iRow-1)^2. Giờ từ i=8, cột xuất phát là 2, và tổng các ô các dòng phía trên là 4, hãy tính thử xem sao.
 
Upvote 0
iRow thì như bác cách của bác ndu. iCol thì tôi gợi ý chút thế này.
Với mỗi 1 giá trị i ta đã biết iRow, với mỗi iRow ta đã biết cột xuất phát của dòng rồi, lấy cột xuất phát + thứ tự của ô tương ứng với giá trị i trong dòng đó là xong. Để tính thứ tự của ô tương ứng với giá trị i thì hãy thử vận dụng các dữ kiện bao gồm i và tổng số ô của các dòng phía trên xem sao.
Ví dụ:
Với N=4, khi i=8 ta có iRow=3, Cột xuất phát là cột 2(N-iRow+1), giờ ta tính tổng các ô của các dòng phía trên(dòng 1 và dòng 2), ở đây là 4=(iRow-1)^2. Giờ từ i=8, cột xuất phát là 2, và tổng các ô các dòng phía trên là 4, hãy tính thử xem sao.
Viết thế này người đọc dễ hiểu cột xuất phát được tính bằng công thức 2*(N-iRow+1). Chỗ này, phần trong ngoặc là chú thích cho số 2.
 
Upvote 0
Mọi người tính cột xuất phát thế nào ấy nhỉ? Tôi tính chỉ bằng 1/2 của Roll và Huuthang thôi: N - iRow + 1
Còn jCol, theo tôi cứ tính jCol xuất phát, sau đó cho jCol tăng 1 dần dần. Khi nào xuống dòng (iRow tăng), tính lại jCol xuất phát mới. Cách tư duy này đơn giản hơn.
Kể cả iRow, nếu tư duy đơn giản thì cho iRow xuất phát = 1, khi thoả điều kiện, iRow = iRow +1

Kết hợp cả 2, iRow tăng, tính lại jCol, cùng 1 điều kiện, chỉ cần 1 If.
 
Lần chỉnh sửa cuối:
Upvote 0
Mọi người tính cột xuất phát thế nào ấy nhỉ? Tôi tính chỉ bằng 1/2 của Roll và Huuthang thôi: N - iRow + 1
Còn jCol, theo tôi cứ tính jCol xuất phát, sau đó cho jCol tăng 1 dần dần. Khi nào xuống dòng (iRow tăng), tính lại jCol xuất phát mới. Cách tư duy này đơn giản hơn.
Kể cả iRow, nếu tư duy đơn giản thì cho iRow xuất phát = 1, khi thoả điều kiện, iRow = iRow +1

Kết hợp cả 2, iRow tăng, tính lại jCol, cùng 1 điều kiện, chỉ cần 1 If.
Cột xuất phát là cột xuất phát của 1 dòng cụ thể nào đó mà, ví dụ tại dòng iRow thì cột xuất phát sẽ là N-iRow+1, còn việc tính iCol thì đúng là hơi khó tư duy, nhưng làm theo cách đó thì thuật toán đọc lên rõ ràng. Cứ với mỗi giá trị ta có Dòng và Cột rồi đem xử lý là xong. Còn phương pháp tăng Dòng và Cột thì có vẻ nó giống với 2 vòng lặp, còn khi thể hiện với 1 vòng lặp thì thuật toán hơi rối.
 
Upvote 0
Xin lỗi RollOver đã đọc nhầm chỗ này: 2(N-iRow+1), nếu viết cách ra và ghi chú 2 (tính bằng N-iRow+1) thì rõ nghĩa hơn. Xin lỗi HuuThang vì HT cũng giải thích chứ không phải tính.

Còn ý tôi khi cho tăng dòng cột là cho người mới học, nếu cách tính toán khó khăn thì nghĩ đến cách tư duy đơn giản trước. Vả lại, nếu ta phát triển tô như trên nhưng 2 lần, 1 lần là lần lượt tăng mổi dòng 1, 3, 5, .., N ô, sau đó giảm mỗi dòng N-2, ..., 5, 3 ,1 ô (dạng hình thoi bằng 2 hình tam giác bài 5, 1 úp 1 lật ngửa); cũng dễ phát triển hơn. Đơn giản vốn dễ phát triển hơn phức tạp mà.
 
Lần chỉnh sửa cuối:
Upvote 0
Gợi ý tiếp câu 5a) cho trường hợp 1 vòng lập
PHP:
iCol = n - iRow + j - (iRow - 1) ^ 2
Với j là biến chạy, n là số nhập trong InputBox
Thí nghiệm thử rồi làm luôn câu 5b) cho trường hợp 1 vòng lập
-------------------------------
Nếu đã hoàn tất, các bạn hãy thử nghĩ đến vấn đề bẫy lỗi xem:
- Với n như thế nào thì code sẽ lỗi?
- Giải pháp bẫy lỗi ra sao?
-------------------------------
(Lập trình viên thường ít khi sợ viết code mà chỉ ngán việc bẫy lỗi thôi!)
 
Upvote 0
Gợi ý tiếp câu 5a) cho trường hợp 1 vòng lập
PHP:
iCol = n - iRow + j - (iRow - 1) ^ 2
Với j là biến chạy, n là số nhập trong InputBox
Thí nghiệm thử rồi làm luôn câu 5b) cho trường hợp 1 vòng lập
-------------------------------
Nếu đã hoàn tất, các bạn hãy thử nghĩ đến vấn đề bẫy lỗi xem:
- Với n như thế nào thì code sẽ lỗi?
- Giải pháp bẫy lỗi ra sao?
-------------------------------
(Lập trình viên thường ít khi sợ viết code mà chỉ ngán việc bẫy lỗi thôi!)
Em xin đưa câu 5a lên theo hướng dẫn của anh NDU như sau:
Mã:
[COLOR=Blue]Sub Tomau3()
Dim iR As Long, iC As Long, N As Long
  Cells.Clear
  N = InputBox("Hay nhap N?")
If N > 128 Or N < 0 Then Exit Sub
 For i = 1 To N ^ 2
   iR = Int(Sqr(i - 1)) + 1
   iC = N - iR + i - (iR - 1) ^ 2
      With Cells(iR, iC)
        .Interior.ColorIndex = 5
        Sleep 50
      End With
 Next
End Sub[/COLOR]
Lỗi khi nhập n theo Em nghĩ như sau:
Lỗi nếu n để trống (tức không nhập số vào box), n<0 và n>128 (vì excel có tổng cộng là 256 cột => 256/2=128, mà ta tô màu đối xứng từ giữa ra 2 bên).
Bẫy lỗi như vậy không biết có đúng không? Các Anh xem và góp ý cho Em nhé!
 
Upvote 0
Em xin đưa câu 5a lên theo hướng dẫn của anh NDU như sau:
Mã:
[COLOR=Blue]Sub Tomau3()
Dim iR As Long, iC As Long, N As Long
  Cells.Clear
  N = InputBox("Hay nhap N?")
If N > 128 Or N < 0 Then Exit Sub
 For i = 1 To N ^ 2
   iR = Int(Sqr(i - 1)) + 1
   iC = N - iR + i - (iR - 1) ^ 2
      With Cells(iR, iC)
        .Interior.ColorIndex = 5
        Sleep 50
      End With
 Next
End Sub[/COLOR]
Lỗi khi nhập n theo Em nghĩ như sau:
Lỗi nếu n để trống (tức không nhập số vào box), n<0 và n>128 (vì excel có tổng cộng là 256 cột => 256/2=128, mà ta tô màu đối xứng từ giữa ra 2 bên).
Bẫy lỗi như vậy không biết có đúng không? Các Anh xem và góp ý cho Em nhé!
Gần được rồi đấy!
Thiếu 1 vài chổ:
- Biến i chưa khai báo
- Chưa bẫy lỗi nhập TEXT vào InputBox ---> Có thể cải tiến thành Application.InputBox("Hay nhap N?", Type:=1)
- Mặc dù nhập số thập phân vào nó vẫn chạy (vì khai báo n as Long) nhưng cũng nên để ý đến việc bẫy lỗi này
- Khó nhất là bẫy lỗi không nhập gì hoặc bấm Cancel trên InputBox
 
Upvote 0
Gần được rồi đấy!
- Mặc dù nhập số thập phân vào nó vẫn chạy (vì khai báo n as Long) nhưng cũng nên để ý đến việc bẫy lỗi này
- Khó nhất là bẫy lỗi không nhập gì hoặc bấm Cancel trên InputBox
Anh chỉ cho Em cách bẫy lỗi 2 thằng trên đi.
Về lỗi thập phân Em định dùng 1 biến tạm T cho nó T=INT(N) có được không nhỉ?
 
Upvote 0
Anh chỉ cho Em cách bẫy lỗi 2 thằng trên đi.
Về lỗi thập phân Em định dùng 1 biến tạm T cho nó T=INT(N) có được không nhỉ?
Về việc bẫy lỗi số thập phân, dùng thế là chính xác rồi
Còn vụ InputBox, đã từng được đề cập trong mục Đố vui về VBA! xem tại đây:
http://www.giaiphapexcel.com/forum/showthread.php?7146-%C4%90%E1%BB%91-vui-v%E1%BB%81-VBA%21&p=232566#post232566
Có thể làm sơ qua thế này:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub Tomau3()
  Dim iR As Long, iC As Long, [COLOR=Red][B]N[/B][/COLOR], i As Long
  Cells.Clear
  [COLOR=Black]N = [B][COLOR=Red]Val([/COLOR][/B]InputBox("Hay nhap N?"))[/COLOR]
  If N > 128 Or N < 0 Or [COLOR=Red]N <> Int(N)[/COLOR] Then Exit Sub
  For i = 1 To N ^ 2
   iR = Int(Sqr(i - 1)) + 1
   iC = N - iR + i - (iR - 1) ^ 2
   Cells(iR, iC).Interior.ColorIndex = 5
   Sleep 50
 Next
End Sub
Quan trọng nằm ở chổ màu đỏ ấy
- Khai báo N kiểu Variant
- N = Val(...) suy ra nếu InputBox là TEXT thì N = 0
- Chấp luôn bấm Cancel và OK khi chưa nhập gì
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom