无聊之余,写了一些小游戏(当然,也有参考别人的代码),当作练手打发时间
(本数独可能并不平衡,可能存在多解,提示功能只提供最基本的提示,避免依赖提示)
import random
import math
sudoku = []
# 生成一个随机的数组
def random_list():
num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
random.shuffle(num_list)
return num_list
def print_grid(arr):
print('------------------------------')
for i in range(9):
for j in range(9):
if arr[i][j] == 0:
print('.', end='')
else:
print(arr[i][j], end='')
if j % 3 == 2:
print(end=' ')
else:
print(end=' ')
print()
if i % 3 == 2 and i != 8:
print()
print('------------------------------')
#生成数独,返回需要填格数
def shudu(arr):
xx = random.randint(50, 51)
x = xx
while x > 0:
x -= 1
y = 0
while arr[y // 9][y % 9] == 0:
y = random.randint(0, 80)
# print(y)
# print(f'x={y // 9},y={y // 9}')
arr[y // 9][y % 9] = 0
print_grid(arr)
return xx
#单元格判断
def bo(x, y, value, a):
if a[x][y] != 0:
print('已有数字')
return False
else:
#判断行列不冲突
for i in range(0, 9):
if a[x][i] == value or a[i][y] == value:
return False
#判断所在格子属于的3*3方块不冲突
xx = x // 3 *3
yy = y // 3 *3
for i in range(0, 3):
if bo and xx + i < 8:
for j in range(0, 3):
if yy + j < 8:
if a[xx + i][yy + j] == value:
return False
return True
#数独操作
def caozuo(x, y, value, a):
if bo(x, y, value, a):
a[x][y] = value
return True
else:
print('填入失败')
return False
#最终判断结果是否合法
def check(a):
for i in range(0, 9):
l1 = []
l2 = []
l3 = []
for j in range(0, 9):
if a[i][j] in l1 or a[j][i] in l2 or a[i//3*3+j//3][i%3*3+j%3] in l3:
print(f'出现重复:x={i},y={j}')
return False
l1.append(a[i][j])
l2.append(a[j][i])
l3.append(a[i // 3 * 3 + j // 3][i % 3 * 3 + j % 3])
return True
def get_row(row):
row_arr = []
for v in sudoku[row]:
if v == 0:
continue
row_arr.append(v)
return row_arr
def get_col(col):
col_arr = []
for i in range(9):
val = sudoku[i][col]
if val == 0:
continue
col_arr.append(sudoku[i][col])
return col_arr
def get_block(num):
col_arr = []
seq = num % 3
col_end = 9 if seq == 0 else seq * 3
row_end = int(math.ceil(num / 3) * 3)
for i in range(row_end - 3, row_end):
for j in range(col_end - 3, col_end):
val = sudoku[i][j]
if val != 0:
col_arr.append(sudoku[i][j])
return col_arr
def get_block_seq(row, col):
col_seq = int(math.ceil((col + 0.1) / 3))
row_seq = int(math.ceil((row + 0.1) / 3))
return 3 * (row_seq - 1) + col_seq
def get_enable_arr(row, col):
avail_arr = random_list()
seq = get_block_seq(row, col)
block = get_block(seq)
row = get_row(row)
col = get_col(col)
unable_arr = list(set(block + row + col))
for v in unable_arr:
if v in avail_arr:
avail_arr.remove(v)
return avail_arr
#开始
def begin(result):
num = shudu(result)
b=[]
while num > 0:
print_grid(result)
print(f'剩余{num}格')
try:
s = input('请输入:').split(' ')
#撤退
if 'b' in s:
break_one(b, result)
num += 1
continue
#提示
if 't' in s:
tishi(result)
continue
x = int(s[0]) - 1
y = int(s[1]) - 1
v = int(s[2])
if caozuo(x, y, v, result):
b.append({'x': x, 'y': y})
num -= 1
except Exception:
continue
print_grid(result)
if check(result):
print('完成')
else:
print('失败')
#后退操作
def break_one(b, a):
if b:
one = b.pop()
a[one['x']][one['y']] = 0
else:
print('不可后退')
return
#提示
def tishi(a):
for i in range(9):
for j in range(9):
if a[i][j] != 0:
continue
b = 1
value = 0
for k in range(1, 10):
if bo(i, j, k, a):
if not value:
value = k
else:
b = 0
break
if b:
print(f'提示:x={i+1}, y={j+1}, v={value}')
return
print('无提示!')
return
#输入方块编号,填充数独
def square(i):
i -= 1
num_list = random_list()
for row in range((i // 3)*3, (i // 3)*3+ 3):
for col in range((i % 3) * 3, (i % 3) * 3):
sudoku[row][col] = num_list.pop()
if __name__ == "__main__":
# 初始化一个9行9列的数组
sudoku = [[0 for i in range(9)] for j in range(9)]
#填充1,5,9号方块
square(1)
square(5)
square(9)
box_list = []
for row in range(9):
for col in range(9):
if sudoku[row][col] == 0:
box_list.append({'row': row, 'col': col})
i = 0
can_num = {}
count = 0
while i < len(box_list):
count += 1
position = box_list[i]
row = position['row']
col = position['col']
key = '%dx%d' % (row, col)
# print(key)
if key in can_num:
enable_arr = can_num[key]
else:
enable_arr = get_enable_arr(row, col)
can_num[key] = enable_arr
# print(can_num)
# x=input('回车')
if len(enable_arr) <= 0:
i -= 1
if key in can_num:
del (can_num[key])
sudoku[row][col] = 0
continue
else:
sudoku[row][col] = enable_arr.pop()
i += 1
result = []
for i in range(0,9):
result.append(sudoku[i].copy())
print_grid(sudoku)
#开始
begin(result)