86707


数独を解くプログラムを作成しています。  
9x9のentryへ問題を入力して、inputボタンを押すことで、entryからデータを読み取って  
outoutボタンを押すことで解答を表示するプログラムです。  
入力した問題のデータはinput_dataのdataにはきちんと保存されているようです(9x9のリスト形式)。  
だた、そのデータが数独を解くための関数には引き渡せていません。  
どうしたら、きちんと渡せますか？

* * *

dataの入力部分は下記ですが、dataにはほしいデータは入っているようですが

[code]

    Button = tk.Button(root, text='Input', command = input_data)
    
[/code]

を実行しても下記にはうまく渡せていません。

[code]

    input_grid = input_data() 
    solve_sudoku(input_grid)
    
[/code]

* * *
[code]

    def input_data():  
        list0 = []
        data = []
        a = 0
        b = 9
            
        for x in range(n*n):
            list0.extend([item[x].get()])
       
        for x in range(n):
            list1 = list0[a:b]
            data.append(list1)
            a = a + n
            b = b + n
                
        for y in range(n):
            for x in range(n):
                if data[y][x] == '':
                    data[y][x] = '0'
        
        for y in range(n):             #もともとは9
            for x in range(n):         #もともとは9
                data[y][x]=int(data[y][x])
        
        print(data) #意図したデータにはなっている(確認用)。
        return data 
    
[/code]

* * *

試しに強制的に、dataにデータを入れ込んでやると正しく

[code]

    input_grid = input_data() 
    solve_sudoku(input_grid)
    
[/code]

でちゃんと計算できています。

[code]

    def input_data():  
        list0 = []
        data = []
        a = 0
        b = 9
            
        for x in range(n*n):
            list0.extend([item[x].get()])
       
        for x in range(n):
            list1 = list0[a:b]
            data.append(list1)
            a = a + n
            b = b + n
                
        for y in range(n):
            for x in range(n):
                if data[y][x] == '':
                    data[y][x] = '0'
        
        for y in range(n):             #もともとは9
            for x in range(n):         #もともとは9
                data[y][x]=int(data[y][x])
        data = [[0, 1, 8, 0, 0, 0, 3, 2, 0],
                  [2, 5, 0, 0, 0, 0, 0, 4, 6],
                  [0, 0, 4, 6, 5, 2, 1, 0, 0],
                  [0, 0, 6, 0, 7, 0, 2, 0, 0],
                  [0, 2, 0, 0, 4, 0, 0, 5, 0],
                  [0, 0, 3, 1, 0, 8, 7, 0, 0],
                  [0, 0, 2, 5, 3, 9, 4, 0, 0],
                  [4, 9, 0, 0, 0, 0, 0, 8, 3],
                  [0, 7, 0, 0, 0, 0, 0, 9, 0]]
        print(data) #意図したデータにはなっている。
        return data 
    
[/code]

以下はコード全体です。

[code]

    import tkinter as tk
    
    root = tk.Tk()
    root.geometry('300x600')
    root.title('test')
    
    n = 9
    i = -1
    backtracks = 0
    input_grid = list()
    item = [0]*n*n
    
    for y in range(n):  
        for x in range(n): 
            i = i + 1
            item[i] = tk.StringVar()
            entry0 = tk.Entry(root, width = 2, textvariable = item[i], justify ='center', font =('',14))
            entry0.grid(row = y, column = x, padx = 2, pady = 2, ipady = 3, sticky=(tk.N, tk.S, tk.E, tk.W))
    
            root.columnconfigure(x, weight = 1)
        # root.rowconfigure(y, weight = 1)
    
    def input_data():#直接データを書き込むとちゃんと動く, dataをsudoku-finalへ入れると動く, dataの出力をを直接入力したら動く    
        list0 = []
        data = []
        a = 0
        b = 9
            
        for x in range(n*n):
            list0.extend([item[x].get()])
       
        for x in range(n):
            list1 = list0[a:b]
            data.append(list1)
            a = a + n
            b = b + n
                
        for y in range(n):
            for x in range(n):
                if data[y][x] == '':
                    data[y][x] = '0'
        
        for y in range(n):             #もともとは9
            for x in range(n):         #もともとは9
                data[y][x]=int(data[y][x])
        
        print(data) #意図したデータにはなっている。
        return data       
        
    def find_next_cell(grid):
        for y in range(n):              #もともとは9
            for x in range(n):          #もともとは9
                if grid[y][x] == 0:
                    # 0の座標を返す
                    return y, x
        # すべてのマスに数字が入っている状態
        return -1, -1
    
    def is_valid(grid, y, x, value):
        # 行のチェック
        is_row = value not in grid[y]
        # 列のチェック
        is_column = value not in [i[x] for i in grid]
        # ブロックを取り出す
        blk_x, blk_y = (x//3)*3 , (y//3)*3
        blk_grid = [i[blk_x:blk_x + 3]for i in grid[blk_y:blk_y +3]]
        # ブロックのチェック
        is_block = value not in sum(blk_grid,[])
        # 有効チェック
        return all([is_row, is_column, is_block])
    
    def solve_sudoku(grid, y=0, x=0):
        global backtracks
        y, x = find_next_cell(grid)
        # 終了判定
        if y == -1 or x == -1:
            return True
        # 入力
        for value in range(1, 10):
            if is_valid(grid, y, x, value):
                grid[y][x] = value
                # 次へ
                if solve_sudoku(grid, y, x):
                    return True
                backtracks += 1
                grid[y][x] = 0
        return False
        
    # 
    def output_data():    #data_set():
        i = -1
        item2 =[0]*n*n
            
        data = input_grid
        
        label0 = tk.Label(root, text = '計算結果', font = ('', 14), height = 1)  
        label0.grid(row = 11, column = 0, columnspan = 4, rowspan = 1)   
        root.columnconfigure(0, weight = 1)
        root.rowconfigure(12, weight = 1)
        
        for y in range(n):
            for x in range(n):
                i = i + 1          
                item2[i] = tk.StringVar()
                entry1 = tk.Entry(root, width = 2, textvariable = item2[i], justify ='center', font =('',14))
                entry1.grid(row = y + 13, column = x, padx = 2, pady = 2, ipady = 3, sticky=(tk.N, tk.S, tk.E, tk.W))
                item2[i] = data[y][x]    
                entry1.insert(tk.END, item2[i])  
               
                root.columnconfigure(x, weight = 1)
            root.rowconfigure(y+13, weight = 1)          
        
    #
    
    Button = tk.Button(root, text='Input', command = input_data)
    #Button = tk.Button(root, text='Input', command = lambda:input_data(data))
    Button.grid(row=0, column=10, padx=2)
    
    input_grid = input_data() #ここはちゃんと渡せている(直接データを書いたら)
    solve_sudoku(input_grid)
    
    Button = tk.Button(root, text='output', command = output_data)
    Button.grid(row=1, column=10, padx=2)
    
    root.mainloop()
    
[/code]


CC BY-SA 4.0
2022-03-05T04:52:39.963
86695
2022-03-05T16:07:19.487
2022-03-05T15:28:00.587
26370
51696
question
python python3
entryから取得したデータがきちんと使用できない


以下のあたりがおかしいでしょう。

  * `def input_data():`関数は取得した入力値(`data`)を最後に戻り値として返していますが、ボタンから呼ばれた時にはそれをどこかに格納する処理が何処にもありません。  
戻り値で返すのではなく、関数の中で必要とする変数(この場合は`input_grid`)に格納する必要があります。  
そして`input_grid`に格納するなら、`def input_data():`関数の最初に`global`宣言をしておく必要があります。

  * `inputボタン処理`と`outputボタン処理`のどちらも`def solve_sudoku(grid, y=0, x=0):`を呼び出す部分がありません。  
`inputボタン処理`の最後か、`outputボタン処理`の`input_grid`からデータをコピーする前に、`solve_sudoku(input_grid)`を呼び出しておく必要があります。

  * `outputボタン`作成や`root.mainloop()`を呼び出す前に行っている以下の処理は、これがあることでかえって問題の原因を判り難くしています。調査のために入れるなら、`output_data`処理の中で何かの変数を`print()`で出力するとかした方が良かったと思われます。

[code]

    input_grid = input_data()
    solve_sudoku(input_grid)
    
[/code]


CC BY-SA 4.0
2022-03-05T16:00:04.593
86707
2022-03-05T16:07:19.487
2022-03-05T16:07:19.487
26370
26370
86695
answer