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,947
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:
(Mở rộng câu 5 a)
Câu 5c


Nhằm mục đích rèn luyện tư duy:
Từ 1 số N, Tô màu từng dòng từ trái qua phải, kết quả như hình (N=6):

To5c.jpg

Câu 5d

Từ 1 số N, Tô màu từng dòng từ trái qua phải, kết quả như hình (N=6):

To5d.jpg

 
Lần chỉnh sửa cuối:
Upvote 0
Liên quan đến bẫy lỗi, ngoại trừ các phương pháp bẫy lỗi trực tiếp từng lỗi một, các lỗi còn lại nếu không lường hết hoặc không biết nên dùng thủ thuật gì, có thể dùng GoTo
Thí dụ:

Mã:
Sub Tomau3()
  Dim iR As Long, iC As Long, N As Long, i As Long
  Cells.Clear
  N = Val(InputBox("Hay nhap N?"))
  If N > 128 Or N < 0 Then Msgbox "Số kỳ quá!": Exit Sub
On Error GoTo Error1
    Your Code here

Error1:
   Msgbox "Cha biet loi gi!"
   Exit Sub
End Sub
 
Upvote 0
(Mở rộng câu 5 a)
Câu 5c


Nhằm mục đích rèn luyện tư duy:
Từ 1 số N, Tô màu từng dòng từ trái qua phải, kết quả như hình (N=6):

View attachment 51157

Câu 5d

Từ 1 số N, Tô màu từng dòng từ trái qua phải, kết quả như hình (N=6):

View attachment 51158

Em xin làm câu 5c với 2 vòng lặp như sau:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Sub Tomau1()
Dim iR As Long, iC As Long, iCols As Long, iRows As Long
  Cells.Clear
  iRows = InputBox("Hay nhap so dong?")
  iCols = iRows * 2 - 1
 For iR = 1 To iRows
   For iC = iR To iCols - iR + 1
      With Cells(iR, iC)
        .Interior.ColorIndex = IIf(iR Mod 2, IIf(iC Mod 2, 3, 4), IIf(iC Mod 2, 4, 3))
        Sleep 50
      End With
    Next iC
 Next iR
End Sub
 

File đính kèm

  • Taptomau.xls
    30.5 KB · Đọc: 16
Lần chỉnh sửa cuối:
Upvote 0
Em xin làm câu 5c với 2 vòng lặp như sau:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Sub Tomau1()
Dim iR As Long, iC As Long, iCols As Long, iRows As Long
  Cells.Clear
  iRows = InputBox("Hay nhap so dong?")
  iCols = iRows * 2 - 1
 For iR = 1 To iRows
   For iC = iR To iCols - iR + 1
      With Cells(iR, iC)
        .Interior.ColorIndex = IIf(iR Mod 2, IIf(iC Mod 2, 3, 4), IIf(iC Mod 2, 4, 3))
        Sleep 50
      End With
    Next iC
 Next iR
End Sub
Tiếp thu bài nhanh ghê!
Cái này: IIf(iR Mod 2, IIf(iC Mod 2, 3, 4), IIf(iC Mod 2, 4, 3))
Thay bằng cái này sẽ gọn hơn: ((iR + iC) Mod 2) + 3
-----------------------------------------------------
Cái "chóp thuận" đã làm rồi
Cái "chóp ngược" cũng đã xong
Vậy chẳng có lý do gì không làm được 5d) nhỉ?
 
Lần chỉnh sửa cuối:
Upvote 0
PHP:
IIf(iR Mod 2, IIf(iC Mod 2, 3, 4), IIf(iC Mod 2, 4, 3))

Có thể thay bằng:

PHP:
IIf((iR + iC) Mod 2, 4, 3)
 
Upvote 0
Câu 5d Em dùng 2 vòng lặp như sau:
Mã:
Sub Tomau2()
Dim iR As Long, iC As Long, N As Long
Dim iCols As Long, iRows As Long, k As Long, L As Long
  Cells.Clear
  N = InputBox("Hay nhap so dong?")
  iRows = N * 2 - 1
  iCols = iRows
 For iR = 1 To iRows
 k = IIf(iR <= N, N - iR + 1, iR - N + 1)
 L = IIf(iR <= N, N + iR - 1, iCols - iR + N)
   For iC = k To L
      With Cells(iR, iC)
        .Interior.ColorIndex = IIf((iR + iC) Mod 2, 3, 4)
        Sleep 50
      End With
    Next iC
 Next iR
End Sub
 

File đính kèm

  • Taptomau.xls
    28 KB · Đọc: 17
Upvote 0
Thật tuyệt! Nhất là ý tưởng tính K và L sau đó For từ K đến L. Thoát ra khỏi cái tư tưởng For luôn bắt đầu từ 1 hoặc bắt đầu từ 1 con số cụ thể. Nói thật, như vậy là tiến nhanh lắm đó!

Bây giờ thử chuyển cả 2 câu c và d thành 1 vòng lặp xem.
 
Lần chỉnh sửa cuối:
Upvote 0
Câu 5d Em dùng 2 vòng lặp như sau:
Mã:
Sub Tomau2()
Dim iR As Long, iC As Long, N As Long
Dim iCols As Long, iRows As Long, k As Long, L As Long
  Cells.Clear
  N = InputBox("Hay nhap so dong?")
  iRows = N * 2 - 1
  iCols = iRows
 For iR = 1 To iRows
 k = IIf(iR <= N, N - iR + 1, iR - N + 1)
 L = IIf(iR <= N, N + iR - 1, iCols - iR + N)
   For iC = k To L
      With Cells(iR, iC)
        .Interior.ColorIndex = IIf((iR + iC) Mod 2, 3, 4)
        Sleep 50
      End With
    Next iC
 Next iR
End Sub
Thu hoạch ban đầu khả quan như vậy thật đáng chức mừng
Việc còn lại bây giờ của bạn là:
- Liên tục "cày" (không được nản)
- Liên tục cải tiến những gì đã làm (đừng tự hài lòng)
- Hãy nghĩ xem trong công việc của bạn, trước đây có file nào đó bạn từng dùng công thức, bây giờ "moi ra" liệu có thể dùng code được không? (cụ thể là dùng đến vòng lập đã học)
-----------------------
Một vài lời khuyên chân tình muốn chia sẻ đến bạn (vì tôi cũng đã từng học như bạn với sư phụ ptm0412)
Vậy nếu có ý tưởng gì hay bạn hãy gữi lên đây để chúng ta cùng bàn bạc nhé
 
Upvote 0
Thu hoạch ban đầu khả quan như vậy thật đáng chức mừng
Việc còn lại bây giờ của bạn là:
- Liên tục "cày" (không được nản)
- Liên tục cải tiến những gì đã làm (đừng tự hài lòng)
- Hãy nghĩ xem trong công việc của bạn, trước đây có file nào đó bạn từng dùng công thức, bây giờ "moi ra" liệu có thể dùng code được không? (cụ thể là dùng đến vòng lập đã học)
-----------------------
Một vài lời khuyên chân tình muốn chia sẻ đến bạn (vì tôi cũng đã từng học như bạn với sư phụ ptm0412)
Vậy nếu có ý tưởng gì hay bạn hãy gữi lên đây để chúng ta cùng bàn bạc nhé
Cảm ơn Anh đã có lời khuyên chân tình, thật tình về VBA Em rất thích và hơn nữa có các Anh tận tình hướng dẫn, giúp đỡ nên Em thấy đây là điều kiện tốt sao Mình không học hỏi nhỉ! Việc học là vô bờ bến, biết càng nhiều càng tốt có sao đâu. Do trình độ còn yếu kém nên hôm qua đến giờ Em nghiên cứu đưa về 1 vòng lặp nhưng chưa được đấy thôi.
 
Upvote 0
Thật tuyệt! Nhất là ý tưởng tính K và L sau đó For từ K đến L. Thoát ra khỏi cái tư tưởng For luôn bắt đầu từ 1 hoặc bắt đầu từ 1 con số cụ thể. Nói thật, như vậy là tiến nhanh lắm đó!

Bây giờ thử chuyển cả 2 câu c và d thành 1 vòng lặp xem.
Để sử dụng 1 vòng lặp cho 2 câu này thì để ý 1 chút ta sẽ thấy câu c sẽ suy luận ngược với logic câu a, tương tự thì câu d sẽ là gộp của câu a và câu c, tuy nhiên logic của cả 2 câu này thì hơi phức tạp. Để dễ cho việc suy nghĩ ta nên thay vì tô màu thì hãy thử thay bằng việc gán theo số thứ tự sẽ dễ hơn. Tôi ví dụ câu c ta điền số như sau:
attachment.php

Khi đó ta sẽ có code như sau:
Mã:
Sub test()
    Dim arrColor, iRow As Long, iCol As Long, iValue As Long, N As Long
    arrColor = Array(3, 4)
    N = InputBox("Hay nhap so dong:")
    For iValue = N ^ 2 To 1 Step -1
        iRow = N - Int(Sqr(iValue - 1))
        iCol = iRow + ((N - iRow + 1) * 2 - 1) - (iValue - (Int(Sqr(iValue - 1))) ^ 2)
        Cells(iRow, iCol) = iValue
        Cells(iRow, iCol).Interior.ColorIndex = arrColor((iRow + iCol) Mod 2)
        Sleep 100
    Next
End Sub
Với câu d thì phức tạp hơn chút nữa.
 

File đính kèm

  • 123.GIF
    123.GIF
    3.6 KB · Đọc: 112
Upvote 0
Gữi bạn MinhCong và tất cả các bạn 1 trò chơi thế này

- Vẽ lên bảng tính 1 vòng tròn và đặt tên cho nó như hình

untitled.JPG

- Tạo 1 code để khi chạy thì nó sẽ quay vòng tròn này, mỗi giây quay 1 góc đúng bằng 1 khía trên mặt đồng hồ ---> Tức sau 60s thì quay đúng 1 vòng
Gợi ý:
- Để quay đúng 1 khía, ta dùng code này:
Mã:
[B]Sheet1.Shapes("VT").IncrementRotation 6[/B]
[B]Sleep 1000
[COLOR=Red]DoEvents[/COLOR][/B]
(phải có DoEvents, nếu không thì sẽ chẳng thấy nó "quay" tí nào)
------------------
- Bạn đầu code chỉ cần quay 1 vòng rồi ngưng
- Sau đó bạn có thể cải tiến bằng cách: nhấn 1 nút thì quay, nhấn nút khác thì ngưng
- Có thể cải tiến tiếp: nhấn 1 nút thì quay... cũng nhấn nút đó lần nữa thì ngưng
(- Nếu khéo tay và có nhiều thời gian hơn, bạn hoàn toàn có thể làm được 3 cây kim để chạy như 1 cái đồng hồ thật sự đấy)
-----------------
Bạn thử xem ---> Tôi nghĩ rằng bạn làm được đấy
 
Lần chỉnh sửa cuối:
Upvote 0
Quay 1 vòng rồi ngưng thì Em làm như thế này:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Sub xoay()
Dim i As Integer
  For i = 1 To 60
     Sheet1.Shapes("VT").IncrementRotation 6
     Sleep 1000
     DoEvents
  Next
End Sub
 
Upvote 0
Em gửi bài tập số 5, xin các sư phụ giúp đỡ
 

File đính kèm

  • Caro(viehoai).xls
    33.5 KB · Đọc: 15
Upvote 0
Hãy nghĩ xem người ta cho "con rắn" này uốn lượn bằng cách nào

untitled.JPG
 

File đính kèm

  • Test.xls
    31 KB · Đọc: 24
Upvote 0
Tiếp theo cho chạy cả 3 kim như sau:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Sub xoay()
Dim i As Long, k As Long, j As Long
  For i = 1 To [COLOR=Red]1800000[/COLOR]
     Sheet1.Shapes("Kimgiay").IncrementRotation 6
     j = i Mod 60: k = i Mod 3600
     If j = 0 Then Sheet1.Shapes("Kimphut").IncrementRotation 6
     If k = 0 Then Sheet1.Shapes("Kimgio").IncrementRotation 6
     Sleep 1000
     DoEvents
  Next
End Sub
Không biết như thế có đúng không?
Số đến của i (1800000) để cho i chạy liên tục không dừng như đồng hồ thì thay 1800000 thành gì nhỉ?
Còn tạo nút bấm: Ta tạo 1 nút CommandButton_click trong sheet 1 luônlà bấm nó chạy được nhưng để dừng nó thì Em chưa tìm ra giải pháp:
Mã:
Private Sub CommandButton1_Click()
xoay
End Sub
 

File đính kèm

  • Xoay.xls
    33.5 KB · Đọc: 24
Lần chỉnh sửa cuối:
Upvote 0
Tiếp theo cho chạy cả 3 kim như sau:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Sub xoay()
Dim i As Long, k As Long, j As Long
  For i = 1 To [COLOR=Red]1800000[/COLOR]
     Sheet1.Shapes("Kimgiay").IncrementRotation 6
     j = i Mod 60: k = i Mod 3600
     If j = 0 Then Sheet1.Shapes("Kimphut").IncrementRotation 6
     If k = 0 Then Sheet1.Shapes("Kimgio").IncrementRotation 6
     Sleep 1000
     DoEvents
  Next
End Sub
Không biết như thế có đúng không?
Số đến của i (1800000) để cho i chạy liên tục không dừng như đồng hồ thì thay 1800000 thành gì nhỉ?
Còn tạo nút bấm: Ta tạo 1 nút CommandButton_click trong sheet 1 luônlà bấm nó chạy được nhưng để dừng nó thì Em chưa tìm ra giải pháp:
Mã:
Private Sub CommandButton1_Click()
xoay
End Sub
Bạn nên tìm hiểu thêm từ hướng dẫn của NDU về DoEvents thử xem sao, khi đó việc bấm để nó dừng thì đơn giản nhất khai báo 1 biến public kiểu boolean, trước khi chạy thì gán nó bằng true, đầu macro chạy kiểm tra nếu là false thì té, khi click vào nút dừng thì gán nó bằng false.
 
Upvote 0
Tiếp theo cho chạy cả 3 kim như sau:
Mã:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Sub xoay()
Dim i As Long, k As Long, j As Long
  For i = 1 To [COLOR=Red]1800000[/COLOR]
     Sheet1.Shapes("Kimgiay").IncrementRotation 6
     j = i Mod 60: k = i Mod 3600
     If j = 0 Then Sheet1.Shapes("Kimphut").IncrementRotation 6
     If k = 0 Then Sheet1.Shapes("Kimgio").IncrementRotation 6
     Sleep 1000
     DoEvents
  Next
End Sub
Không biết như thế có đúng không?
Số đến của i (1800000) để cho i chạy liên tục không dừng như đồng hồ thì thay 1800000 thành gì nhỉ?
Còn tạo nút bấm: Ta tạo 1 nút CommandButton_click trong sheet 1 luônlà bấm nó chạy được nhưng để dừng nó thì Em chưa tìm ra giải pháp:
Mã:
Private Sub CommandButton1_Click()
xoay
End Sub
Bạn để ý thế này:
- Kim phút có tốc độ = 1 / 60 lần kim giây
- Kim giờ có tốc độ = 1 / 12 lần kim phút = 1 / 720 lần kim giây

Vậy có thể viết thế này:
PHP:
With Sheet1
  .Shapes("Kimgiay").IncrementRotation 6
  .Shapes("Kimphut").IncrementRotation 1 / 10
  .Shapes("Kimgio").IncrementRotation 1 / 120
End With
Ngoài ra, do không biết vòng lập chạy từ bao nhiêu đến bao nhiêu nên ta không thể dùng For... Next mà phải Do... Loop ---> Chạy đến khi nào dừng là do ta tự quyết định
Có thể dùng 1 biến Check để kiểm tra như rollover79 vừa hướng dẫn, hoặc có thể dùng Caption của CommandButton để điều khiển ---> Khi Caption = Start thì chạy, Khi Caption = Stop thì ngưng
Kiểu vầy:
PHP:
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
Private Sub CommandButton1_Click()
  With Sheet1
    With .CommandButton1
      .Caption = IIf(.Caption = "Start", "Stop", "Start")
    End With
    Do
      .Shapes("Kimgiay").IncrementRotation 6
      .Shapes("Kimphut").IncrementRotation 1 / 10
      .Shapes("Kimgio").IncrementRotation 1 / 120
      Sleep 1000
      DoEvents
    Loop Until .CommandButton1.Caption = "Start"
  End With
End Sub
Chưa test ---> Bạn kiểm tra lại giúp tôi với
Code này viết cho CommandButton nha
 
Upvote 0
1. Về 5c và 5 d của viehoai, Chạy đúng rồi. Suy luận cũng giống như Minhcong, nên xứng đáng gọi là tiến bộ.

2. Về con rắn, ẹc ẹc, sleep ít quá hay sao, nó nhảy như điên chứ đâu có gọi là uốn lượn ... Mà nhảy rồi là hông có chịu dừng, khiếp!
Gợi ý:
- Đó là chart XY scatter, y = sin(x)
- sleep 1 miếng, thay số đầu tiên của X bằng X + 1 gia số nhỏ nhỏ. Các gia trị khác của X cũng nên dùng công thức bằng giá trị X trước đó cộng với 1 số nhỏ nhỏ, để chạy theo ô đầu tiên.

3. Về cái đồng hồ:
- Code của Minhcong cũng chạy, kim giờ và phút chạy kiểu đồng hồ quart, code ndu chạy kiểu đồng hồ lên giây. (quart là khi kim giây chạy đủ 1 vòng, kim phút nhảy 1 cái kịch. Lên giây là kim phút cũng có di chuyển từng chút một xem như liên tục)
- Tuy nhiên, code Minh Công chưa xét đến chuyện i Mod 60 =0 ở vị trí khởi đầu bất kỳ, nên kim phút nhảy cái kịch khi kim giây ở vị trí khác số 12 của đồng hồ. Để giải quyết có thể dùng 1 đoạn code chạy đầu tiên, đoạn code này lấy giờ hiện tại, xoay cả 3 kim đến vị trí đúng của nó rồi mới bắt đầu chạy. Ngoài ra, điều kiện để kim phút và kim giờ "nhảy cái kịch" cũng phải sửa lại.

Thí dụ:
PHP:
Sub Gettime()
Dim Ctime As Double, hr As Long, mt As Long, sd As Long
Ctime = Time
hr = Hour(Ctime) Mod 12
mt = Minute(Ctime)
sd = Second(Ctime)
With Sheet1
    .Shapes("Kimgio").Rotation = hr * 30
    .Shapes("Kimphut").Rotation = mt * 6
    .Shapes("Kimgiay").Rotation = sd * 6
End With
End Sub

Ghi chú: Code mẫu này lấy giờ cho kim đồng hồ chạy kiểu Quart. Lấy vị trí cho kim chạy kiểu lên giây cần chính xác hơn nữa.
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom