2010年7月16日 星期五

數獨

數獨
 數獨說明(略)。
 請設計一個程式,可以幫助玩家提示空格中尚可填入的數字。
 例如,(如輸入範例test3.txt),第5行第3列的位置尚可填入1這個數字;第6行第7列的位置尚可填入7與8這兩個數字;而第5行第5列的位置已有數字填入則輸出0。
 輸入說明:
 輸入的第一列到第九列為數獨資料,每一列由九個數字所組成。數字1到9為已填入的數字,0代表尚未填入數值的空格,每個數字與數字間的區隔為一個空白符號。第十列及以後的資料為要提示位置的座標(座標的定義方式為右上角為9 1,左下角為1 9,第一個數字代表行,第二個數字代表列),當為0 0 時表示結束。
 輸入範例:test3.txt
4 0 0 8 0 5 0 1 0 
2 0 0 0 0 9 0 8 0
6 0 8 0 0 3 4 9 0
0 0 5 0 2 0 6 0 0 
0 0 1 0 7 0 9 0 0
0 0 7 0 8 0 3 0 0
0 9 0 1 0 0 0 0 2
0 8 0 4 0 0 0 0 9
0 3 0 6 0 2 0 0 7
5 3
6 7
5 5
0 0 
 輸出說明:每個提示位置有一列輸出結果,表示尚可填入的數字,請由小到大排列。每個數字與數字間的區隔為一個空白符號。若該位置已有填入數字,或找不到提示的數字則輸出0。
 輸出範例:result3.txt
1
7 8
0

額外說明:
1.這題雖然前面已經做過數獨遊戲了,但是一來每個人還沒做解題的部份;二來用以往的競賽題目,來了解題目可以怎麼出。
2.還是要再提醒每個人,不可以只用這樣的一個例子去解而已。要自己再加輸入例子,再將輸出的結果也一併貼出來。
3.尤其要注意「邊界值」,像這題的1 1和9 9或是9 1或是1 9。像前一題總和檢查時,要注意的邊界值就是用100個數字的數列及用2個數字的數列來當成是輸入例子。

熊掌
數獨輸入資料錯誤修正

7 則留言:

  1. 老師
    這個輸入範例
    好像只有8列說@.@

    回覆刪除
  2. Dim sq(81) As Integer, L1(9) As Integer, sqAns(81) As String
    Private Sub Form_Load()
    Me.Hide
    Open App.Path & "\in.txt" For Input As #1
    Open App.Path & "\out.txt" For Output As #2
    For i = 1 To 9
    Line Input #1, strL
    For j = 1 To 9
    L1(j) = Val(Mid(strL, j, 1))
    sq((i - 1) * 9 + j) = L1(j)
    sqAns((i - 1) * 9 + j) = "1 2 3 4 5 6 7 8 9 "
    Next j
    Next i
    Do
    Input #1, QuA, QuB
    If QuA = 0 And QuB = 0 Then Exit Do
    Call check(QuA, QuB)
    Loop
    Close #2
    Close #1
    End
    End Sub
    Public Sub check(x, y)
    chN = sq((y - 1) * 9 + x)
    If chN <> 0 Then
    sqAns((y - 1) * 9 + x) = "0"
    Print #2, sqAns((y - 1) * 9 + x)
    Exit Sub
    Else
    For i = 1 To 9
    A = sq((i - 1) * 9 + x)
    sqAns((y - 1) * 9 + x) = Replace(sqAns((y - 1) * 9 + x), A & " ", "")
    Next i
    For i = 1 To 9
    A = sq((y - 1) * 9 + i)
    sqAns((y - 1) * 9 + x) = Replace(sqAns((y - 1) * 9 + x), A & " ", "")
    Next i
    If x <= 3 Then
    Ac = 0
    ElseIf x >= 7 Then
    Ac = 2
    Else
    Ac = 1
    End If

    If y <= 3 Then
    Bc = 0
    ElseIf y >= 7 Then
    Bc = 2
    Else
    Bc = 1
    End If
    For i = 0 To 2
    For j = 0 To 2
    A = sq(Ac * 3 + Bc * 27 + 1 + j + i * 9)
    sqAns((y - 1) * 9 + x) = Replace(sqAns((y - 1) * 9 + x), A & " ", "")
    Next j
    Next i
    End If
    Print #2, sqAns((y - 1) * 9 + x)
    End Sub

    輸入1:
    258407130
    040189250
    900235684
    613540900
    520370418
    487002500
    102854096
    095620001
    804791320
    3 3
    8 4
    5 6
    9 9
    2 9
    0 0

    輸出1:
    1
    7
    1 6
    5
    6

    輸入2:
    014980007
    009057020
    700200008
    900340085
    025100760
    308502900
    102700000
    503020100
    097830502
    7 1
    6 7
    3 3
    8 4
    5 6
    9 9
    2 9
    0 0


    輸出2:
    3 6
    4 5 6 9
    6
    0
    6 7
    0
    0

    回覆刪除
  3. Dim dat(9, 9) As String
    Dim num(3, 9) As Boolean
    Private Sub Form_Load()
    Me.Hide
    Open App.Path & "\result3.txt" For Output As #2
    Open App.Path & "\test3.txt" For Input As #1
    k = 1
    Do
    Line Input #1, step
    For i = 1 To 9
    dat(i, k) = Mid(step, i, 1)
    Next i
    k = k + 1
    Loop Until k = 10
    Do
    Input #1, x, y
    If x = 0 And y = 0 Then Exit Sub
    If dat(x, y) <> 0 Then
    Print 0#; 2,
    GoTo here
    End If
    Call renum
    For i = 1 To 9
    st = dat(i, y)
    num(1, Val(st)) = True
    Next i
    For i = 1 To 9
    st = dat(x, i)
    num(2, Val(st)) = True
    Next i
    stx = (x - 1) \ 3
    sty = (y - 1) \ 3
    For i = 1 To 3
    For j = 1 To 3
    st = dat(stx * 3 + i, sty * 3 + j)
    num(3, Val(st)) = True
    Next j
    Next i
    For j = 1 To 9
    If (num(1, j) = False) And (num(2, j) = False) And (num(3, j) = False) Then Print #2, j;
    Next j
    Print #2,
    here:
    Loop
    Close #1
    Close #2
    End
    End Sub

    Public Sub renum()
    For j = 1 To 3
    For i = 1 To 9
    num(j, i) = False
    Next i
    Next j
    End Sub

    回覆刪除
  4. 你們應該是要參加技藝競賽的吧!
    可以一起討論題目嗎?

    回覆刪除
  5. 挖~"~有不認識的@@

    回覆刪除
  6. 小白好,
    1.輸入範例打錯了,不好意思,已修正。
    2.你的程式OK,用的方式蠻好的,用副程式,使程式看來清楚。
    一樣分三區,直行、橫行和3x3小區塊,也是用replace來置換,清楚。
    3.程式開頭結尾,也都記得加上hide和end,很好。

    阿揚好,
    1.用2維陣列,更容易思考,也蠻好的。
    2.print 0#;2, 應該是錯誤的吧。print #2,0吧。
    3. 用goto here的方式,容易在除錯時,找不到錯誤點,請小心使用。用if then else 就可以了啦。
    4. 你的記錄有沒有出現過的num(3,9),其實還是只要num(9)就夠用了啊。
    還是一樣先設定每個為false,只要在直的橫的小區有出現,就給它設為true,重複設true,也沒關係啊,只有沒有設過true的格,才是可以出現的數字啊。
    5.但是,總的來說,除了第2點的小錯之外,程式應該是OK的。

    毛毛蟲好,
    原則上是OK的,你也可以將程式給po上來,或是問別人的程式中不懂的地方,當然,看到別人的程式有錯誤,也可以直接說出來,或是可能的錯誤...反正,試試看吧,目前並沒有很封閉的意思。

    回覆刪除
  7. Dim M(9, 9) As Integer
    Dim A As Integer, B As Integer
    Dim V As Boolean
    Private Sub Form_Load()

    Open App.Path & "/in.txt" For Input As #1
    Open App.Path & "/out.txt" For Output As #2
    For i = 1 To 9
    For j = 1 To 9
    Input #1, M(i, j)
    Print M(i, j);
    Next j
    Print
    Next i

    Do While Not EOF(1)
    Input #1, B, A
    V = False
    If A = 0 And B = 0 Then Exit Sub
    If M(A, B) <> 0 Then GoTo Jump
    For i = 1 To 9
    For j = 1 To 9
    If M(A, j) = i Or M(j, B) = i Then GoTo Jump
    Next j

    c = ((A - 1) \ 3) * 3: d = ((B - 1) \ 3) * 3
    For j = c + 1 To c + 3
    For k = d + 1 To d + 3
    If M(j, k) = i Then GoTo Jump
    Next k
    Next j

    V = True
    Print #2, i;
    Jump:
    Next i
    If V = False Then Print #2, "0";
    Print #2,
    Loop
    Close #2
    Close #1
    End Sub

    回覆刪除