You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Sudo/main/main.py

424 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
Name:Sudo Game
Date:2024.04.09
Version:1.0
Description:None
"""
import pickle
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
import sudo as sd
def replace_element(arr, old_val, new_val):
return list(map(lambda x: new_val if x == old_val else x, arr))
def count_occurrences(lst, x, mode):
count = 0
if mode == 0:
for item in lst:
if item == x:
count += 1
else:
for row in lst:
for item in row:
if item == x:
count += 1
return count
class Form(Form1):
def __init__(self):
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.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)
self.B0_3.clicked.connect(self.put_num)
self.B0_4.clicked.connect(self.put_num)
self.B0_5.clicked.connect(self.put_num)
self.B0_6.clicked.connect(self.put_num)
self.B0_7.clicked.connect(self.put_num)
self.B0_8.clicked.connect(self.put_num)
self.B1_0.clicked.connect(self.put_num)
self.B1_1.clicked.connect(self.put_num)
self.B1_2.clicked.connect(self.put_num)
self.B1_3.clicked.connect(self.put_num)
self.B1_4.clicked.connect(self.put_num)
self.B1_5.clicked.connect(self.put_num)
self.B1_6.clicked.connect(self.put_num)
self.B1_7.clicked.connect(self.put_num)
self.B1_8.clicked.connect(self.put_num)
self.B2_0.clicked.connect(self.put_num)
self.B2_1.clicked.connect(self.put_num)
self.B2_2.clicked.connect(self.put_num)
self.B2_3.clicked.connect(self.put_num)
self.B2_4.clicked.connect(self.put_num)
self.B2_5.clicked.connect(self.put_num)
self.B2_6.clicked.connect(self.put_num)
self.B2_7.clicked.connect(self.put_num)
self.B2_8.clicked.connect(self.put_num)
self.B3_0.clicked.connect(self.put_num)
self.B3_1.clicked.connect(self.put_num)
self.B3_2.clicked.connect(self.put_num)
self.B3_3.clicked.connect(self.put_num)
self.B3_4.clicked.connect(self.put_num)
self.B3_5.clicked.connect(self.put_num)
self.B3_6.clicked.connect(self.put_num)
self.B3_7.clicked.connect(self.put_num)
self.B3_8.clicked.connect(self.put_num)
self.B4_0.clicked.connect(self.put_num)
self.B4_1.clicked.connect(self.put_num)
self.B4_2.clicked.connect(self.put_num)
self.B4_3.clicked.connect(self.put_num)
self.B4_4.clicked.connect(self.put_num)
self.B4_5.clicked.connect(self.put_num)
self.B4_6.clicked.connect(self.put_num)
self.B4_7.clicked.connect(self.put_num)
self.B4_8.clicked.connect(self.put_num)
self.B5_0.clicked.connect(self.put_num)
self.B5_1.clicked.connect(self.put_num)
self.B5_2.clicked.connect(self.put_num)
self.B5_3.clicked.connect(self.put_num)
self.B5_4.clicked.connect(self.put_num)
self.B5_5.clicked.connect(self.put_num)
self.B5_6.clicked.connect(self.put_num)
self.B5_7.clicked.connect(self.put_num)
self.B5_8.clicked.connect(self.put_num)
self.B6_0.clicked.connect(self.put_num)
self.B6_1.clicked.connect(self.put_num)
self.B6_2.clicked.connect(self.put_num)
self.B6_3.clicked.connect(self.put_num)
self.B6_4.clicked.connect(self.put_num)
self.B6_5.clicked.connect(self.put_num)
self.B6_6.clicked.connect(self.put_num)
self.B6_7.clicked.connect(self.put_num)
self.B6_8.clicked.connect(self.put_num)
self.B7_0.clicked.connect(self.put_num)
self.B7_1.clicked.connect(self.put_num)
self.B7_2.clicked.connect(self.put_num)
self.B7_3.clicked.connect(self.put_num)
self.B7_4.clicked.connect(self.put_num)
self.B7_5.clicked.connect(self.put_num)
self.B7_6.clicked.connect(self.put_num)
self.B7_7.clicked.connect(self.put_num)
self.B7_8.clicked.connect(self.put_num)
self.B8_0.clicked.connect(self.put_num)
self.B8_1.clicked.connect(self.put_num)
self.B8_2.clicked.connect(self.put_num)
self.B8_3.clicked.connect(self.put_num)
self.B8_4.clicked.connect(self.put_num)
self.B8_5.clicked.connect(self.put_num)
self.B8_6.clicked.connect(self.put_num)
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
hours = self.total_seconds // 3600
minutes = (self.total_seconds % 3600) // 60
seconds = self.total_seconds % 60
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, 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_with_answer[int(info[0][1]), int(info[0][3])] = int(info[1])
except Exception as e:
print(e)
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_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")
if del_cnt == cnt:
QMessageBox.information(self, '提示', '成功')
self.change_flag = 0
self.timer.stop()
else:
# 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_with_answer, stack
b = self.sender()
x = int(b.objectName()[1])
y = int(b.objectName()[3])
old_text = b.text()
if b.text() == ' ':
cnt = cnt + 1
stack.append(f'B{x}_{y},{old_text}')
# print(stack)
if self.R_1.isChecked():
b.setText("1")
subject_with_answer[x, y] = 1
if self.R_2.isChecked():
b.setText("2")
subject_with_answer[x, y] = 2
if self.R_3.isChecked():
b.setText("3")
subject_with_answer[x, y] = 3
if self.R_4.isChecked():
b.setText("4")
subject_with_answer[x, y] = 4
if self.R_5.isChecked():
b.setText("5")
subject_with_answer[x, y] = 5
if self.R_6.isChecked():
b.setText("6")
subject_with_answer[x, y] = 6
if self.R_7.isChecked():
b.setText("7")
subject_with_answer[x, y] = 7
if self.R_8.isChecked():
b.setText("8")
subject_with_answer[x, y] = 8
if self.R_9.isChecked():
b.setText("9")
subject_with_answer[x, y] = 9
if cnt == del_cnt:
self.check_sudo()
else:
self.check_sudo(1)
self.change_flag = 1
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
self.timer.start()
# 选择难度
if self.R_e.isChecked():
level = 1
if self.R_m.isChecked():
level = 2
if self.R_h.isChecked():
level = 3
# 这里可以用多线程
sudo = sd.Sudo()
subject_with_answer = sudo.createSubjectByLevel(level).subject_with_answer
del_cnt = sudo.get_del_cnt()
# 打印参考答案
# sudo.print_sudo()
# print(sudo)
self.translate(sudo.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 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()