|
|
|
@ -4,11 +4,9 @@
|
|
|
|
|
Version:1.0
|
|
|
|
|
Description:None
|
|
|
|
|
"""
|
|
|
|
|
import pickle
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import random
|
|
|
|
|
|
|
|
|
|
from PySide6.QtCore import QTimer
|
|
|
|
|
from PySide6.QtCore import QTimer, QPropertyAnimation, QRect, QPoint
|
|
|
|
|
from PySide6.QtWidgets import *
|
|
|
|
|
from PySide6.QtGui import QIcon
|
|
|
|
|
from win.win import Ui_Form as Form1
|
|
|
|
@ -39,14 +37,27 @@ class Form(Form1):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.setupUi(self)
|
|
|
|
|
self.total_seconds = 0
|
|
|
|
|
self.change_flag = 0
|
|
|
|
|
self.B_save.setDisabled(True)
|
|
|
|
|
# self.test()
|
|
|
|
|
self.konami_code = [65, 66, 65, 66]
|
|
|
|
|
# self.lll =[]
|
|
|
|
|
self.konami_index = 0
|
|
|
|
|
self.pushButton.clicked.connect(self.B_back)
|
|
|
|
|
self.B_S.clicked.connect(self.translate)
|
|
|
|
|
self.B_S.clicked.connect(self.B_S_fun)
|
|
|
|
|
self.B_save.clicked.connect(self.B_save_fun)
|
|
|
|
|
self.B_read.clicked.connect(self.B_read_fun)
|
|
|
|
|
self.B_rule.clicked.connect(self.B_rule_fun)
|
|
|
|
|
|
|
|
|
|
self.timer = QTimer()
|
|
|
|
|
self.shake_timer = QTimer(self)
|
|
|
|
|
self.shake_times = 0
|
|
|
|
|
self.shake_timer.timeout.connect(self.shake_window)
|
|
|
|
|
self.timer.setInterval(1000)
|
|
|
|
|
self.timer.timeout.connect(self.update_time)
|
|
|
|
|
self.init_bt()
|
|
|
|
|
|
|
|
|
|
def init_bt(self):
|
|
|
|
|
self.B0_0.clicked.connect(self.put_num)
|
|
|
|
|
self.B0_1.clicked.connect(self.put_num)
|
|
|
|
|
self.B0_2.clicked.connect(self.put_num)
|
|
|
|
@ -129,6 +140,38 @@ class Form(Form1):
|
|
|
|
|
self.B8_7.clicked.connect(self.put_num)
|
|
|
|
|
self.B8_8.clicked.connect(self.put_num)
|
|
|
|
|
|
|
|
|
|
def closeEvent(self, event):
|
|
|
|
|
if self.change_flag == 1:
|
|
|
|
|
message_box = QMessageBox()
|
|
|
|
|
message_box.setWindowTitle("提示")
|
|
|
|
|
message_box.setText("是否要保存进度?")
|
|
|
|
|
message_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
|
|
|
|
message_box.setDefaultButton(QMessageBox.No)
|
|
|
|
|
yes_button = message_box.button(QMessageBox.Yes)
|
|
|
|
|
yes_button.clicked.connect(self.B_save_fun)
|
|
|
|
|
|
|
|
|
|
no_button = message_box.button(QMessageBox.No)
|
|
|
|
|
|
|
|
|
|
message_box.exec()
|
|
|
|
|
|
|
|
|
|
# 重写窗口按键事件
|
|
|
|
|
def keyPressEvent(self, event):
|
|
|
|
|
global sudo
|
|
|
|
|
key = event.key()
|
|
|
|
|
try:
|
|
|
|
|
if key == self.konami_code[self.konami_index]:
|
|
|
|
|
self.konami_index += 1
|
|
|
|
|
if self.konami_index == len(self.konami_code):
|
|
|
|
|
sudo.print_sudo()
|
|
|
|
|
self.konami_index = 0
|
|
|
|
|
else:
|
|
|
|
|
self.konami_index = 0
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.konami_index = 0
|
|
|
|
|
# self.lll.append(key)
|
|
|
|
|
# print(self.lll)
|
|
|
|
|
|
|
|
|
|
def update_time(self):
|
|
|
|
|
self.total_seconds += 1
|
|
|
|
|
|
|
|
|
@ -139,61 +182,141 @@ class Form(Form1):
|
|
|
|
|
time_str = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
|
|
|
self.lcdNumber.display(time_str)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def B_rule_fun(self):
|
|
|
|
|
rules = """
|
|
|
|
|
以下是数独游戏的规则:
|
|
|
|
|
|
|
|
|
|
1. 每个数独游戏由一个9x9的方格组成,共计81个小方格。
|
|
|
|
|
2. 方格被划分为9个3x3的小方格,每个小方格内的数字不得重复。
|
|
|
|
|
3. 每行必须包含数字1到9,且不能重复。
|
|
|
|
|
4. 每列必须包含数字1到9,且不能重复。
|
|
|
|
|
5. 每个3x3的小方格内必须包含数字1到9,且不能重复。
|
|
|
|
|
6. 游戏开始时,一些方格内可能包含了一些已知的数字(称为“提示数字”),玩家需要根据这些提示数字来推理并填充其余的方格。
|
|
|
|
|
7. 玩家通过逻辑推理和试错来填充空白方格,直到所有方格都填满,且符合数独规则为止。
|
|
|
|
|
8. 如果玩家填写的数字与已有的数字冲突,或者某一行、列、或小方格内存在重复的数字,则游戏失败。
|
|
|
|
|
9. 当所有方格都填满,且符合数独规则时,游戏胜利。
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
QMessageBox.information(self, '提示', rules)
|
|
|
|
|
def B_save_fun(self):
|
|
|
|
|
global sudo, cnt, del_cnt
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 保存已填处,第一位用于记录cnt,第二位记录delcnt,第三位记录time
|
|
|
|
|
answer_list = [cnt, del_cnt, self.total_seconds]
|
|
|
|
|
|
|
|
|
|
with open('as.pickle', 'wb') as f:
|
|
|
|
|
# 使用pickle的dump函数将对象写入文件
|
|
|
|
|
pickle.dump(answer_list, f)
|
|
|
|
|
|
|
|
|
|
with open('sudo.pickle', 'wb') as f:
|
|
|
|
|
# 使用pickle的dump函数将对象写入文件
|
|
|
|
|
pickle.dump(sudo, f)
|
|
|
|
|
|
|
|
|
|
QMessageBox.information(self, '提示', '保存成功')
|
|
|
|
|
self.change_flag = 0
|
|
|
|
|
except Exception as e:
|
|
|
|
|
QMessageBox.information(self, '提示', f'保存发生错误:{e}')
|
|
|
|
|
|
|
|
|
|
def B_read_fun(self):
|
|
|
|
|
global sudo, cnt, subject_with_answer, del_cnt
|
|
|
|
|
self.change_flag = 0
|
|
|
|
|
self.B_save.setDisabled(False)
|
|
|
|
|
answer_list = None
|
|
|
|
|
with open('as.pickle', 'rb') as f:
|
|
|
|
|
# 使用pickle的load函数从文件中读取对象
|
|
|
|
|
answer_list = pickle.load(f)
|
|
|
|
|
|
|
|
|
|
with open('sudo.pickle', 'rb') as f:
|
|
|
|
|
# 使用pickle的load函数从文件中读取对象
|
|
|
|
|
sudo = pickle.load(f)
|
|
|
|
|
|
|
|
|
|
# 配置计数器和计时器
|
|
|
|
|
cnt = answer_list[0]
|
|
|
|
|
del_cnt = answer_list[1]
|
|
|
|
|
print(cnt)
|
|
|
|
|
stack.clear()
|
|
|
|
|
self.total_seconds = answer_list[2]
|
|
|
|
|
self.timer.start()
|
|
|
|
|
|
|
|
|
|
# 映射题目并配置答案进度
|
|
|
|
|
self.translate(sudo.subject)
|
|
|
|
|
subject_with_answer = sudo.subject_with_answer
|
|
|
|
|
i = 1
|
|
|
|
|
self.translate(subject_with_answer, 1)
|
|
|
|
|
|
|
|
|
|
def B_back(self):
|
|
|
|
|
global stack,cnt
|
|
|
|
|
global stack, cnt, subject_with_answer
|
|
|
|
|
self.change_flag = 1
|
|
|
|
|
try:
|
|
|
|
|
top = stack.pop()
|
|
|
|
|
info = top.split(",", 1)
|
|
|
|
|
b = self.findChild(QPushButton, info[0])
|
|
|
|
|
|
|
|
|
|
if info[1] == ' ':
|
|
|
|
|
info[1] = 0
|
|
|
|
|
b.setText(' ')
|
|
|
|
|
cnt = cnt - 1
|
|
|
|
|
else:
|
|
|
|
|
b.setText(info[1])
|
|
|
|
|
subject[info[0][1], info[0][3]] = int(info[1])
|
|
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
print("Stack Empty")
|
|
|
|
|
subject_with_answer[int(info[0][1]), int(info[0][3])] = int(info[1])
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(e)
|
|
|
|
|
|
|
|
|
|
def check_sudo(self):
|
|
|
|
|
global cnt, del_cnt, subject
|
|
|
|
|
def check_sudo(self, mode=0):
|
|
|
|
|
global cnt, del_cnt, subject_with_answer
|
|
|
|
|
f = 1
|
|
|
|
|
|
|
|
|
|
for row_index in range(9):
|
|
|
|
|
for col_index in range(9):
|
|
|
|
|
num = subject[row_index, col_index]
|
|
|
|
|
|
|
|
|
|
# 获取该格子对应的行、列、九宫格
|
|
|
|
|
sudo_row = sd.get_row(subject, row_index)
|
|
|
|
|
sudo_col = sd.get_col(subject, col_index)
|
|
|
|
|
sudo_block = sd.get_block(subject, row_index, col_index)
|
|
|
|
|
# print(num)
|
|
|
|
|
# print(sudo_row)
|
|
|
|
|
# print(sudo_col)
|
|
|
|
|
# print(sudo_block)
|
|
|
|
|
|
|
|
|
|
cnt_oc1 = count_occurrences(sudo_row, num, 0)
|
|
|
|
|
cnt_oc2 = count_occurrences(sudo_col, num, 0)
|
|
|
|
|
cnt_oc3 = count_occurrences(sudo_block, num, 1)
|
|
|
|
|
if cnt_oc1 != 1 or cnt_oc2 != 1 or cnt_oc3 != 1:
|
|
|
|
|
f = 0
|
|
|
|
|
break
|
|
|
|
|
num = subject_with_answer[row_index, col_index]
|
|
|
|
|
if num == 0:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
# 获取该格子对应的行、列、九宫格
|
|
|
|
|
sudo_row = sd.get_row(subject_with_answer, row_index)
|
|
|
|
|
sudo_col = sd.get_col(subject_with_answer, col_index)
|
|
|
|
|
sudo_block = sd.get_block(subject_with_answer, row_index, col_index)
|
|
|
|
|
|
|
|
|
|
cnt_oc1 = count_occurrences(sudo_row, num, 0)
|
|
|
|
|
cnt_oc2 = count_occurrences(sudo_col, num, 0)
|
|
|
|
|
cnt_oc3 = count_occurrences(sudo_block, num, 1)
|
|
|
|
|
# print(cnt_oc1, cnt_oc2, cnt_oc3)
|
|
|
|
|
if cnt_oc1 != 1 or cnt_oc2 != 1 or cnt_oc3 != 1:
|
|
|
|
|
f = 0
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if f == 0:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if f == 1:
|
|
|
|
|
print("yes")
|
|
|
|
|
QMessageBox.information(self, '提示','成功')
|
|
|
|
|
self.timer.stop()
|
|
|
|
|
# print("yes")
|
|
|
|
|
if del_cnt == cnt:
|
|
|
|
|
QMessageBox.information(self, '提示', '成功')
|
|
|
|
|
self.change_flag = 0
|
|
|
|
|
self.timer.stop()
|
|
|
|
|
else:
|
|
|
|
|
print("no")
|
|
|
|
|
QMessageBox.information(self, '提示','失败')
|
|
|
|
|
# print("no")
|
|
|
|
|
if mode == 1:
|
|
|
|
|
self.shake_timer.start(30)
|
|
|
|
|
else:
|
|
|
|
|
QMessageBox.information(self, '提示', '失败')
|
|
|
|
|
|
|
|
|
|
def shake_window(self):
|
|
|
|
|
self.shake_times += 1
|
|
|
|
|
if self.shake_times == 5:
|
|
|
|
|
self.shake_times = 0
|
|
|
|
|
self.shake_timer.stop()
|
|
|
|
|
else:
|
|
|
|
|
if self.shake_times % 2 == 0:
|
|
|
|
|
self.move(self.x() + 7, self.y())
|
|
|
|
|
else:
|
|
|
|
|
self.move(self.x() - 7, self.y())
|
|
|
|
|
|
|
|
|
|
def put_num(self):
|
|
|
|
|
global cnt, del_cnt, subject, stack
|
|
|
|
|
global cnt, del_cnt, subject_with_answer, stack
|
|
|
|
|
|
|
|
|
|
b = self.sender()
|
|
|
|
|
x = int(b.objectName()[1])
|
|
|
|
@ -204,43 +327,48 @@ class Form(Form1):
|
|
|
|
|
cnt = cnt + 1
|
|
|
|
|
|
|
|
|
|
stack.append(f'B{x}_{y},{old_text}')
|
|
|
|
|
print(stack)
|
|
|
|
|
# print(stack)
|
|
|
|
|
|
|
|
|
|
if self.R_1.isChecked():
|
|
|
|
|
b.setText("1")
|
|
|
|
|
subject[x, y] = 1
|
|
|
|
|
subject_with_answer[x, y] = 1
|
|
|
|
|
if self.R_2.isChecked():
|
|
|
|
|
b.setText("2")
|
|
|
|
|
subject[x, y] = 2
|
|
|
|
|
subject_with_answer[x, y] = 2
|
|
|
|
|
if self.R_3.isChecked():
|
|
|
|
|
b.setText("3")
|
|
|
|
|
subject[x, y] = 3
|
|
|
|
|
subject_with_answer[x, y] = 3
|
|
|
|
|
if self.R_4.isChecked():
|
|
|
|
|
b.setText("4")
|
|
|
|
|
subject[x, y] = 4
|
|
|
|
|
subject_with_answer[x, y] = 4
|
|
|
|
|
if self.R_5.isChecked():
|
|
|
|
|
b.setText("5")
|
|
|
|
|
subject[x, y] = 5
|
|
|
|
|
subject_with_answer[x, y] = 5
|
|
|
|
|
if self.R_6.isChecked():
|
|
|
|
|
b.setText("6")
|
|
|
|
|
subject[x, y] = 6
|
|
|
|
|
subject_with_answer[x, y] = 6
|
|
|
|
|
if self.R_7.isChecked():
|
|
|
|
|
b.setText("7")
|
|
|
|
|
subject[x, y] = 7
|
|
|
|
|
subject_with_answer[x, y] = 7
|
|
|
|
|
if self.R_8.isChecked():
|
|
|
|
|
b.setText("8")
|
|
|
|
|
subject[x, y] = 8
|
|
|
|
|
subject_with_answer[x, y] = 8
|
|
|
|
|
if self.R_9.isChecked():
|
|
|
|
|
b.setText("9")
|
|
|
|
|
subject[x, y] = 9
|
|
|
|
|
subject_with_answer[x, y] = 9
|
|
|
|
|
|
|
|
|
|
if cnt == del_cnt:
|
|
|
|
|
self.check_sudo()
|
|
|
|
|
else:
|
|
|
|
|
self.check_sudo(1)
|
|
|
|
|
self.change_flag = 1
|
|
|
|
|
|
|
|
|
|
def translate(self):
|
|
|
|
|
global cnt, del_cnt, subject, stack
|
|
|
|
|
def B_S_fun(self):
|
|
|
|
|
global cnt, del_cnt, stack, sudo, subject_with_answer
|
|
|
|
|
|
|
|
|
|
# 清零
|
|
|
|
|
self.change_flag = 1
|
|
|
|
|
self.B_save.setDisabled(False)
|
|
|
|
|
cnt = 0
|
|
|
|
|
stack.clear()
|
|
|
|
|
self.total_seconds = 0
|
|
|
|
@ -253,39 +381,43 @@ class Form(Form1):
|
|
|
|
|
level = 2
|
|
|
|
|
if self.R_h.isChecked():
|
|
|
|
|
level = 3
|
|
|
|
|
max_clear_count = 64
|
|
|
|
|
min_clear_count = 14
|
|
|
|
|
each_level_count = (max_clear_count - min_clear_count) / 5
|
|
|
|
|
level_start = min_clear_count + (level - 1) * each_level_count
|
|
|
|
|
del_cnt = del_nums = random.randrange(level_start, level_start + each_level_count)
|
|
|
|
|
|
|
|
|
|
# 生成数独
|
|
|
|
|
sudo = sd.create_base_sudo()
|
|
|
|
|
sd.random_sudo(sudo, 50)
|
|
|
|
|
|
|
|
|
|
# 这里可以用多线程
|
|
|
|
|
sudo = sd.Sudo()
|
|
|
|
|
subject_with_answer = sudo.createSubjectByLevel(level).subject_with_answer
|
|
|
|
|
del_cnt = sudo.get_del_cnt()
|
|
|
|
|
# 打印参考答案
|
|
|
|
|
sd.print_sudo(sudo)
|
|
|
|
|
# 出题
|
|
|
|
|
subject = sd.get_sudo_subject(sudo, del_nums)
|
|
|
|
|
# sudo.print_sudo()
|
|
|
|
|
# print(sudo)
|
|
|
|
|
self.translate(sudo.subject)
|
|
|
|
|
|
|
|
|
|
for row_index, row in enumerate(subject):
|
|
|
|
|
def translate(self, nparray, mode=0):
|
|
|
|
|
# 将np数组内容映射到按钮上
|
|
|
|
|
for row_index, row in enumerate(nparray):
|
|
|
|
|
row_list = list(map(str, row.tolist()))
|
|
|
|
|
row_list = replace_element(row_list, '0', ' ')
|
|
|
|
|
for single_index, single in enumerate(row_list):
|
|
|
|
|
# 找到对象名为对应坐标的按钮
|
|
|
|
|
b = self.findChild(QPushButton, 'B' + str(row_index) + '_' + str(single_index))
|
|
|
|
|
# 将值映射到按钮上
|
|
|
|
|
b.setText(single)
|
|
|
|
|
if single != ' ':
|
|
|
|
|
b.setDisabled(True)
|
|
|
|
|
else:
|
|
|
|
|
b.setDisabled(False)
|
|
|
|
|
# 禁用空值按钮
|
|
|
|
|
if mode == 0:
|
|
|
|
|
if single != ' ':
|
|
|
|
|
b.setDisabled(True)
|
|
|
|
|
else:
|
|
|
|
|
b.setDisabled(False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
cnt = 0
|
|
|
|
|
del_cnt = 0
|
|
|
|
|
stack = []
|
|
|
|
|
subject_with_answer = None
|
|
|
|
|
sudo = None
|
|
|
|
|
app = QApplication()
|
|
|
|
|
win = Form()
|
|
|
|
|
# app.setStyleSheet(qdarkstyle.load_stylesheet())
|
|
|
|
|
win.setWindowIcon(QIcon('src/sudo32.png'))
|
|
|
|
|
win.show()
|
|
|
|
|
app.exec()
|
|
|
|
|