20212216王恒钊《Python程序设计》实验四报告

课程:《Python程序设计》
班级: 2122
姓名: 王恒钊
学号:20212216
实验教师:王志强
实验日期:2022年5月28日
必修/选修: 公选课

一、实验要求

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
注:在华为ECS服务器(OpenOuler系统)和物理机(Windows/Linux系统)上使用VIM、PDB、IDLE、Pycharm等工具编程实现。

二、实验内容

通过Python写一个数独小游戏,并在华为云服务器上保存并运行。

三、实验灵感

数独是一款风靡全球的小游戏,能提高我们的思维和判断能力。借着这次实验,决定写一个数独小游戏。

四、实验过程

(一)搜索相关的python编写数独的注意事项

(二)编写数独代码

import random
import math
 
matrix = []
sds = []
 
 
def get_random_unit():
    _num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    random.shuffle(_num_list)
    return _num_list
 
 
def print_grid(arr):
    for i in range(9):
        sds.append(arr[i])
 
 
def get_row(row):
    row_arr = []
    for v in matrix[row]:
        if v == 0:
            continue
        row_arr.append(v)
    return row_arr
 
 
def get_col(col):
    col_arr = []
    for i in range(9):
        val = matrix[i][col]
        if val == 0:
            continue
        col_arr.append(matrix[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 = matrix[i][j]
            if val != 0:
                col_arr.append(matrix[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 = get_random_unit()
    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 main():
    can_num = {}
    count = 0
   
    for i in range(9):
        matrix.append([0] * 9)
 
    num_list = get_random_unit()
    for row in range(3):
        for col in range(3):
            matrix[row][col] = num_list.pop(0)
 
    num_list = get_random_unit()
    for row in range(3, 6):
        for col in range(3, 6):
            matrix[row][col] = num_list.pop(0)
 
    num_list = get_random_unit()
    for row in range(6, 9):
        for col in range(6, 9):
            matrix[row][col] = num_list.pop(0)
 
    box_list = []
    for row in range(9):
        for col in range(9):
            if matrix[row][col] == 0:
                box_list.append({'row': row, 'col': col})
 
    i = 0
    while i < len(box_list):
        count += 1
        position = box_list[i]
        row = position['row']
        col = position['col']
        key = '%dx%d' % (row, col)
        if key in can_num:
            enable_arr = can_num[key]
        else:
            enable_arr = get_enable_arr(row, col)
            can_num[key] = enable_arr
 
        if len(enable_arr) <= 0:
            i -= 1
            if key in can_num:
                del (can_num[key])
            matrix[row][col] = 0
            continue
        else:
            matrix[row][col] = enable_arr.pop()
            i += 1
 
    print_grid(matrix)
 
if __name__ == "__main__":
    main()
 
# --------------------华丽の分割线--------------------
 
ac_num = 0
pausE = True
difficulty = 3
 
from tkinter import *
from tkinter import ttk
import time
import pygame as py
 
def setDiff(difF):
    global difficulty
    global diff
    try:
        difficulty = int(difF)
        diff.destroy()
    except:
        pass
diff = Tk()
diff.title('难度选择')
diff.geometry('300x90')
diff.resizable(0,0)
Label(diff,text='选择你要挑战的难度!(0~9)',font=('微软雅黑',9)).pack()
cmb = ttk.Combobox(diff)
cmb.pack()
cmb['value'] = (0,1,2,3,4,5,6,7,8,9)
Button(diff,text='我选好了',command=lambda:setDiff(cmb.get())).pack()
diff.mainloop()
window = Tk()
window.title('数独')
window.geometry('390x500')
window.resizable(0,0)
begin_time = 0
steps = 0
rights = 0
wrongs = 0
dwc = difficulty*9
ac_name = None
 
list = range(1,82)
try:
    ran = random.sample(list,dwc)
except:
    if difficulty > 9:
        ran = random.sample(list,9)
    elif difficulty < 0:
        ran = random.sample(list,1)
    print('难度输入出现问题 你将无法通关')
try:
    py.mixer.init()
    py.mixer.music.load('bg2.mp3')
    py.mixer.music.play(-1)
except:
    print('未检测到名为 bg2.mp3  的背景音乐')
   
def setBlock(num,name):
    global begin_time
    if begin_time == 0:
        begin_time = time.time()
    global ac_name
    global ac_num
    if ac_name != name and name != None and ac_name != None:
        ac_name.config(text='?',bg='orange',activebackground='orange',relief='groove')
    if name.cget('bg') != 'green':
        name.config(text='···',relief='sunken',bg='lightblue',activebackground='lightblue')
        ac_name = name
        ac_num = num
    else:
        ac_name = None
def setNum(num):
    global ac_name
    global begin_time
    global dwc
    global ac_num
    global re
    global difficulty
    global steps
    global wrongs
    global rights
    global steP
    try:
        b_color = ac_name.cget('bg')
        if ac_num == num:
            ac_name.config(text='√',activebackground='green',relief='groove',bg='green')
        else:  
            ac_name.config(text='×',activebackground='red',relief='groove')
        ac_name.flash()
        ac_name.flash()
        if ac_num == num:
            ac_name.config(text=str(num),activebackground='green',background='green',relief='groove')
        else:
            ac_name.config(text='?',bg='orange',activebackground='orange',relief='groove')
        if ac_name.cget('bg') == 'green' and b_color == 'lightblue':
            dwc -= 1
            ac_name = None
            rights += 1
            steps += 1
        elif b_color == 'lightblue' and ac_name.cget('bg') == 'orange':
            ac_name = None
            wrongs += 1
            steps += 1
        if dwc == 0:
            ac_name = None
            print('恭喜,你赢了!')
            Label(window,text='恭喜,你赢了!',font=('微软雅黑',30),bg='lightgreen').place(x=52,y=50)
            use_time = round(time.time()-begin_time,1)
            Label(window,text='用时'+str(use_time)+'秒  正确率'+str(round((rights/steps)*100,1))+'%',bg='yellow').place(x=113,y=121)
        re.config(text='剩余数字数量:'+str(dwc)+' 难度等级:'+str(difficulty))
        steP.config(text='步数:'+str(steps)+' 正确:'+str(rights)+' 错误:'+str(wrongs))
        ac_name = None
    except:
        pass
def tipSs():
    '''global sds
    for ynfo in sds:
        print(ynfo)'''
    global ac_num
    global ac_name
    try:
        ac_name.config(text=str(ac_num))
        ac_name.flash()
        ac_name.config(text='···')
    except:
        pass
def pauseOr(bgm):
    global pausE
    if pausE == True:
        py.mixer.music.pause()
        Button(window,text='♪',font=('楷体',7),relief='sunken',bg='white',command=lambda:pauseOr(bgm)).place(x=365,y=11)
        pausE = False
    elif pausE == False:
        py.mixer.music.unpause()
        Button(window,text='♫',font=('楷体',7),relief='sunken',bg='green',command=lambda:pauseOr(bgm)).place(x=365,y=11)
        pausE = True
j=0
i=0.7
_count = 1
wz = False
# 这里通过win10计算器,两年前的项目写出了算法
def spaceBtn(i,j,ri,rj):
    name =  'a'+str(i+1)+str(j+1)
    name = Button(window,text='?',font=('微软雅黑',10),relief='groove',bg='orange',activebackground='orange',command=lambda:setBlock(sds[i][j],name))
    name.place(x=rj*36,y=ri*38,width=30,height=30)
def numBtn(num):
    Button(window,text=str(num),font=('楷体',15),relief='sunken',bg='white',activebackground='blue',command=lambda:setNum(num)).place(x=x*42+9,y=380,width=37,height=37)
for info in sds:
    for jnfo in info:
        j+=1
        for znfo in ran:
            if _count == znfo:
                wz = True
        _count += 1
        if wz == True:
            spaceBtn(round(i-1),j-1,i,j)
            wz = False
        else:
            Label(window,text=jnfo,font=('微软雅黑',10),relief='ridge',bg='grey').place(x=j*36,y=i*38,width=30,height=30)
    j=0
    i+=1
for x in range(0,9):
    numBtn(x+1)
Button(window,text='提示',command=tipSs).place(x=50,y=430)
bgm = Button(window,text='♫',font=('楷体',7),relief='sunken',bg='green',command=lambda:pauseOr(bgm)).place(x=365,y=11)
re = Label(window,text='剩余数字数量:'+str(dwc)+' 难度等级:'+str(difficulty),relief='sunken')
re.place(x=185,y=470)
steP = Label(window,text='步数:'+str(steps)+' 正确:'+str(rights)+' 错误:'+str(wrongs),relief='sunken')
steP.place(x=5,y=470)
window.mainloop()

(三)试着在vscode上运行

 

 选择难度为0—9

 

 试运行

 

 (四)购买华为云服务器

 

 (五)上传源码至ECS主机

 

 (六)在putty上登陆云服务器

 

 

 

 

 

 (七)下载tkinter

 

 由于第一次下载时未截屏,展示第二次下载的结果

(八)下载xterm

 

 同样首次下载未截屏

(九)下载xauth

 

 同样首次下载未截屏

(十)开始在华为云服务器里运行

 

 

 

 

 

 

 

 

 

 

 

 

五、实验反思

实验过程中遇到的问题

在最终运行时,发现运行不了,多次检查并询问同学后发现是代码里同时用到了pygame和tkinter。同学说这两个不能同时存在。

解决方法

修改代码,将代码中用到的pygame部分删去,后成功运行,但是这样就舍弃了背景音乐,最终在华为云服务器上运行后没有了音乐,不过数独游戏能正常玩。

 

 

最后附上修改后的代码:

import random
import math
 
matrix = []
sds = []
 
 
def get_random_unit():
    _num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    random.shuffle(_num_list)
    return _num_list
 
 
def print_grid(arr):
    for i in range(9):
        sds.append(arr[i])
 
 
def get_row(row):
    row_arr = []
    for v in matrix[row]:
        if v == 0:
            continue
        row_arr.append(v)
    return row_arr
 
 
def get_col(col):
    col_arr = []
    for i in range(9):
        val = matrix[i][col]
        if val == 0:
            continue
        col_arr.append(matrix[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 = matrix[i][j]
            if val != 0:
                col_arr.append(matrix[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 = get_random_unit()
    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 main():
    can_num = {}
    count = 0
   
    for i in range(9):
        matrix.append([0] * 9)
 
    num_list = get_random_unit()
    for row in range(3):
        for col in range(3):
            matrix[row][col] = num_list.pop(0)
 
    num_list = get_random_unit()
    for row in range(3, 6):
        for col in range(3, 6):
            matrix[row][col] = num_list.pop(0)
 
    num_list = get_random_unit()
    for row in range(6, 9):
        for col in range(6, 9):
            matrix[row][col] = num_list.pop(0)
 
    box_list = []
    for row in range(9):
        for col in range(9):
            if matrix[row][col] == 0:
                box_list.append({'row': row, 'col': col})
 
    i = 0
    while i < len(box_list):
        count += 1
        position = box_list[i]
        row = position['row']
        col = position['col']
        key = '%dx%d' % (row, col)
        if key in can_num:
            enable_arr = can_num[key]
        else:
            enable_arr = get_enable_arr(row, col)
            can_num[key] = enable_arr
 
        if len(enable_arr) <= 0:
            i -= 1
            if key in can_num:
                del (can_num[key])
            matrix[row][col] = 0
            continue
        else:
            matrix[row][col] = enable_arr.pop()
            i += 1
 
    print_grid(matrix)
 
if __name__ == "__main__":
    main()
 
# --------------------华丽の分割线--------------------
 
ac_num = 0
pausE = True
difficulty = 3
 
from tkinter import *
from tkinter import ttk
import time
# import pygame as py
 
def setDiff(difF):
    global difficulty
    global diff
    try:
        difficulty = int(difF)
        diff.destroy()
    except:
        pass
diff = Tk()
diff.title('难度选择')
diff.geometry('300x90')
diff.resizable(0,0)
Label(diff,text='选择你要挑战的难度!(0~9)',font=('微软雅黑',9)).pack()
cmb = ttk.Combobox(diff)
cmb.pack()
cmb['value'] = (0,1,2,3,4,5,6,7,8,9)
Button(diff,text='我选好了',command=lambda:setDiff(cmb.get())).pack()
diff.mainloop()
window = Tk()
window.title('数独')
window.geometry('390x500')
window.resizable(0,0)
begin_time = 0
steps = 0
rights = 0
wrongs = 0
dwc = difficulty*9
ac_name = None
 
list = range(1,82)
try:
    ran = random.sample(list,dwc)
except:
    if difficulty > 9:
        ran = random.sample(list,9)
    elif difficulty < 0:
        ran = random.sample(list,1)
    print('难度输入出现问题 你将无法通关')
# try:
#     py.mixer.init()
#     py.mixer.music.load('bg2.mp3')
#     py.mixer.music.play(-1)
# except:
#     print('未检测到名为 bg2.mp3  的背景音乐')
   
def setBlock(num,name):
    global begin_time
    if begin_time == 0:
        begin_time = time.time()
    global ac_name
    global ac_num
    if ac_name != name and name != None and ac_name != None:
        ac_name.config(text='?',bg='orange',activebackground='orange',relief='groove')
    if name.cget('bg') != 'green':
        name.config(text='···',relief='sunken',bg='lightblue',activebackground='lightblue')
        ac_name = name
        ac_num = num
    else:
        ac_name = None
def setNum(num):
    global ac_name
    global begin_time
    global dwc
    global ac_num
    global re
    global difficulty
    global steps
    global wrongs
    global rights
    global steP
    try:
        b_color = ac_name.cget('bg')
        if ac_num == num:
            ac_name.config(text='√',activebackground='green',relief='groove',bg='green')
        else:  
            ac_name.config(text='×',activebackground='red',relief='groove')
        ac_name.flash()
        ac_name.flash()
        if ac_num == num:
            ac_name.config(text=str(num),activebackground='green',background='green',relief='groove')
        else:
            ac_name.config(text='?',bg='orange',activebackground='orange',relief='groove')
        if ac_name.cget('bg') == 'green' and b_color == 'lightblue':
            dwc -= 1
            ac_name = None
            rights += 1
            steps += 1
        elif b_color == 'lightblue' and ac_name.cget('bg') == 'orange':
            ac_name = None
            wrongs += 1
            steps += 1
        if dwc == 0:
            ac_name = None
            print('恭喜,你赢了!')
            Label(window,text='恭喜,你赢了!',font=('微软雅黑',30),bg='lightgreen').place(x=52,y=50)
            use_time = round(time.time()-begin_time,1)
            Label(window,text='用时'+str(use_time)+'秒  正确率'+str(round((rights/steps)*100,1))+'%',bg='yellow').place(x=113,y=121)
        re.config(text='剩余数字数量:'+str(dwc)+' 难度等级:'+str(difficulty))
        steP.config(text='步数:'+str(steps)+' 正确:'+str(rights)+' 错误:'+str(wrongs))
        ac_name = None
    except:
        pass
def tipSs():
    '''global sds
    for ynfo in sds:
        print(ynfo)'''
    global ac_num
    global ac_name
    try:
        ac_name.config(text=str(ac_num))
        ac_name.flash()
        ac_name.config(text='···')
    except:
        pass
def pauseOr(bgm):pass
    # global pausE
    # if pausE == True:
    #     py.mixer.music.pause()
    #     Button(window,text='♪',font=('楷体',7),relief='sunken',bg='white',command=lambda:pauseOr(bgm)).place(x=365,y=11)
    #     pausE = False
    # elif pausE == False:
    #     py.mixer.music.unpause()
    #     Button(window,text='♫',font=('楷体',7),relief='sunken',bg='green',command=lambda:pauseOr(bgm)).place(x=365,y=11)
    #     pausE = True
j=0
i=0.7
_count = 1
wz = False
# 这里通过win10计算器,两年前的项目写出了算法
def spaceBtn(i,j,ri,rj):
    name =  'a'+str(i+1)+str(j+1)
    name = Button(window,text='?',font=('微软雅黑',10),relief='groove',bg='orange',activebackground='orange',command=lambda:setBlock(sds[i][j],name))
    name.place(x=rj*36,y=ri*38,width=30,height=30)
def numBtn(num):
    Button(window,text=str(num),font=('楷体',15),relief='sunken',bg='white',activebackground='blue',command=lambda:setNum(num)).place(x=x*42+9,y=380,width=37,height=37)
for info in sds:
    for jnfo in info:
        j+=1
        for znfo in ran:
            if _count == znfo:
                wz = True
        _count += 1
        if wz == True:
            spaceBtn(round(i-1),j-1,i,j)
            wz = False
        else:
            Label(window,text=jnfo,font=('微软雅黑',10),relief='ridge',bg='grey').place(x=j*36,y=i*38,width=30,height=30)
    j=0
    i+=1
for x in range(0,9):
    numBtn(x+1)
Button(window,text='提示',command=tipSs).place(x=50,y=430)
bgm = Button(window,text='♫',font=('楷体',7),relief='sunken',bg='green',command=lambda:pauseOr(bgm)).place(x=365,y=11)
re = Label(window,text='剩余数字数量:'+str(dwc)+' 难度等级:'+str(difficulty),relief='sunken')
re.place(x=185,y=470)
steP = Label(window,text='步数:'+str(steps)+' 正确:'+str(rights)+' 错误:'+str(wrongs),relief='sunken')
steP.place(x=5,y=470)
window.mainloop()

六、全课总结

不得不说,每一次的实验都很难,要付出大量的时间与精力,让人头疼。但是做完实验,写完实验报告后对实验的印象加深了很多,确实效果显著。

python到这里就结束了,上课学习python的经历就此结束,但是课下学习python的路还会继续走。在python课上学到了很多,也扩充了自己的知识面与知识点。

我对老师的讲课有一小点建议,希望以后的python课后期不要这么赶,跨度也尽量不要这么大,在python课上到后面几节,我能明显感受到每节课的跨度很大,对初学者很不友好。

感谢老师的悉心指导,让我收获颇丰。

最后的最后,还是那句话:

人生苦短,我用Python!

 

参考资料

_tkinter.TclError: no display name and no $DISPLAY environment variable - 简书 (jianshu.com)

Putty+Xming远程登录Ubuntu 16.04图形界面_Linux教程_Linux公社-Linux系统门户网站 (linuxidc.com)

 

posted @ 2022-05-28 21:56  钊九晚五  阅读(82)  评论(0编辑  收藏  举报