Github項目地址
https://github.com/zxw0621/demo/tree/master/20177596/src
PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鍾) | 實際耗時(分鍾) |
---|---|---|---|
Planning | 計划 | 30 | 20 |
Estimate | 估計這個任務需要多少時間 | 600 | 700 |
Development | 開發 | 300 | 200 |
Analysis | 需求分析 (包括學習新技術) | 30 | 20 |
Design Spec | 生成設計文檔 | 30 | 30 |
Design Review | 設計復審 | 60 | 30 |
Coding Standard | 代碼規范 (為目前的開發制定合適的規范) | 30 | 20 |
Design | 具體設計 | 30 | 30 |
Coding | 具體編碼 | 60 | 60 |
Code Review | 代碼復審 | 60 | 20 |
Test | 測試(自我測試,修改代碼,提交修改) | 30 | 10 |
Reporting | 報告 | 20 | 20 |
Test Repor | 測試報告 | 20 | 20 |
Size Measurement | 計算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后總結, 並提出過程改進計划 | 30 | 30 |
合計 | 1350 | 1230 |
思路描述
審題
- 按照數獨游戲的規定,給一張含有若干的數字隨機分布在網格的圖,在每個位置上的數在列和行上不能重復出現,在4、6、8、9階的數獨表中,每個小宮格內不能有重復的數出現。
- 用cmd命令行的形式讀出寫入文件,並傳入參數。
- 要實現多個九宮格一起處理,且解答情況唯一。
- 要求用java和c++,這里順便學習下python(從大一剛學那會就學習過一點點,后來忙於學習學校安排的課程后沒怎么學了,以后還想接觸些膾炙人口的新鮮事物,比如某些大佬開口就是什么大數據,雲計算,人工智能的)
功能模塊設計
流程圖
1.定位模塊
def new_locate(_x_, _y_, _a_, _b_): #上面的版本是學習小鄧同學的定位
'''
新版定位
:param _x_:
:param _y_:
:return:
'''
if M % 3 == 0: #通過向下取整計算出 大的九宮格能分成幾行幾列的小九宮格
_c_ = 3
_r_ = int(M / 3)
elif M % 2 == 0:
_c_ = 2
_r_ = int(M / 2)
_a_ = int(_x_ // _c_ * _c_)
_b_ = int(_y_ // _r_ * _r_)c_:_r_
return _a_, _b_, _c_, _r_ #這里返回 _a_: 當前元素所在的小九宮格 左上角的橫坐標
# _b_: 當前元素所在的小九宮格 左上角的縱坐標
# _c_: 大九宮格被分成了 r行 c列的小九宮格
# _r_:
# def locate(_x_, _y_, _a_, _b_): #莽夫判斷 respect阿傳
# '''
# 確定當前元素所在九宮格位置
# :param _x_:
# :param _y_:
# :param a:
# :param b:
# :return:
# '''
# if 0 <= _x_ < 3 and 0 <= _y_ < 3:
# _a_ = 0
# _b_ = 0
#
# if 3 <= _x_ < 6 and 0 <= _y_ < 3:
# _a_ = 3
# _b_ = 0
#
# if 6 <= _x_ < 9 and 0 <= _y_ < 3:
# _a_ = 6
# _b_ = 0
#
# if 0 <= _x_ < 3 and 3 <= _y_ < 6:
# _a_ = 0
# _b_ = 3
#
# if 0 <= _x_ < 3 and 6 <= _y_ < 9:
# _a_ = 0
# _b_ = 6
#
# if 3 <= _x_ < 6 and 3 <= _y_ < 6:
# _a_ = 3
# _b_ = 3
#
# if 3 <= _x_ < 6 and 6 <= _y_ < 9:
# _a_ = 3
# _b_ = 6
#
# if 6 <= _x_ < 9 and 3 <= _y_ < 6:
# _a_ = 6
# _b_ = 3
#
# if 6 <= _x_ < 9 and 6 <= _y_ < 9:
# _a_ = 6
# _b_ = 6
# return _a_, _b_
2.行列無重復判斷模塊
def fun(_x_, _y_):
'''
確定行列上不重復
:param inde__x_:
:param _y_:
:param num:
:return:
'''
for _i_ in range(M):
if _i_ != _x_ and DATA[_i_][_y_] == DATA[_x_][_y_]:#遍歷行
return 0
for j in range(M):
if j != _y_ and DATA[_x_][j] == DATA[_x_][_y_]:#遍歷列
return 0
_a_ = 0
_b_ = 0
_a_, _b_, _c_, _r_ = new_locate(_x_, _y_, _a_, _b_)
for _i_ in range(_a_, _a_ + _c_):
for j in range(_b_, _b_ + _r_):
if _i_ != _x_ and j != _y_ and DATA[_i_][j] == DATA[_x_][_y_]:#遍歷小九宮格
return 0
return 1
3.深度優先搜索模塊
def dfs(_x_, _y_):
'''
深搜
:param _x_:
:param _y_:
:return:
'''
#這里就相當於給沒填數字的格子 嘗試可能填的數
if _x_ > M - 1:
disp()
elif DATA[_x_][_y_] != 0:
if _y_ == M - 1:
dfs(_x_ + 1, 0)
else:
dfs(_x_, _y_ + 1)
else:
for _i_ in range(1, M + 1):
DATA[_x_][_y_] = _i_ #從1到M 賦值嘗試
if fun(_x_, _y_) == 1:
if _y_ == M - 1:
dfs(_x_ + 1, 0)
else:
dfs(_x_, _y_ + 1)
DATA[_x_][_y_] = 0 #回溯
4.文件的寫入讀出
for line in FP.readlines(): #讀出
arr = line.strip().split(" ")
if arr[0] >= '0':
int_arr = list(map(int, arr))
DATA.append(int_arr)
#分行讀出 每隔一個空格讀一個數 map函數用於將讀取到的內容轉int整型 保存成列表數組List
寫入有個write函數就完事了
5.命令行輸入
python命令行輸入用 import sys
然后用sys.argv[x]數組輸入
sys.argv[0]表示的是你的py文件名 用sys.argv[1......] 按你輸入的順序賦值給你要的參數變量
性能改進
改進了定位模塊 上文有提到 實現3-9階九宮格都可以定位
心路歷程
一拿到題目的時候,我是拒絕的。彭琛老師發布的作業也太快了,媽媽再也不用擔心我手指不靈活了,媽媽再也不用擔心我會出門花錢了,媽媽再也不用擔心洗發水用的完了,這算法 題,我裂開,這怎么做,算法我學了啥。大一:彭琛老師教給我們冒泡排序法。大二:數據結構課上,冒泡排序法,我一氣呵成,老師說我這發量還不行。大三:算法課上,各種指針嵌套遞歸回溯,一到實驗課,冒泡排序法信手捏來。預測大四:《論冒泡排序法的基本思想》朱旭煒20177596.doc。其實沒有老師發布的作業,我真不會接觸算法這些東西,既然發布了,還是先端正下態度哈。完成代碼編寫的過程也是十分艱辛,在CSDN上也看了一些其他大佬的實現思路,結合作業的要求完成。
關於《構建之法》:
下次我一定看!
單元測試
import unittest
from sudoku import new_locate
class MyTestCase(unittest.TestCase):
def test_fun(self):
test_num=new_locate(5,8,0,0)
self.assertEqual(test_num,(3,6,3,3))
if __name__ == '__main__':
unittest.main()
#計算新定位模塊是否能正常計算出_a_,_b_,_c_,_r_
靜態檢測(工具:PyLint)
剛完成的代碼那會,點pylint,出來好多啊,結合上次作業出現的問題總結下:
- 寫完代碼前,點擊Code - > Reformat Code, 在pycharm最上面那條找得到,這個效果是整理代碼,點完這個都能消除很多提醒和警告
- 變量命名的方法,提醒你大寫你就全大寫,提醒snake命名就寫成_name_ 像這樣的,當然我也不知道這樣規范不,請大佬教育下我
- def函數塊里面要寫注釋,這個提醒也太人性化了,怕別人看你的代碼時候看不懂,不然就C0116提醒了,這個搞了我好久,專門折磨我這種強迫症,類似的不寫注釋還有C0114,寫在最上面就好了,告訴別人你這整個代碼干嘛用的
- 還有就是要簡化 i f 判斷,特別是多個並列條件的判斷
- 還有減少else后面不必要的return ,不要寫else: 這樣的,第一個判斷里面有return的話,程序都出去了,沒必要再else:return return x
- 暫無其他問題了,以后碰到會繼續補充,也請大佬們指指點點下
總結
雖然沒做過算法題,通過自己查資料,咨詢大佬后還是對問題的解答有所思路的,python挺好用的。希望彭琛老師發布作業的速度可以慢點,頂不住,早點開學吧,我太難了。
大佬の指指點點
- @不負真人:你這函數沒引入DATA可以直接操作DATA的值嗎?
def dfs(_x_, _y_):
'''
深搜
:param _x_:
:param _y_:
:return:
'''
#這里就相當於給沒填數字的格子 嘗試可能填的數
if _x_ > M - 1:
disp()
elif DATA[_x_][_y_] != 0: # < - 為啥能直接用?
if _y_ == M - 1:
dfs(_x_ + 1, 0)
else:
dfs(_x_, _y_ + 1)
else:
for _i_ in range(1, M + 1):
DATA[_x_][_y_] = _i_ #從1到M 賦值嘗試
if fun(_x_, _y_) == 1:
if _y_ == M - 1:
dfs(_x_ + 1, 0)
else:
dfs(_x_, _y_ + 1)
DATA[_x_][_y_] = 0 #回溯
博主親自給這位爺查閱資料,尋找一些不會讓自己尷尬且強有力的論證,在python語言中:
-
在函數中對全局變量只是進行引用而不是進行修改時,不需要使用global關鍵字
-
修改全局變量,需要使用global聲明
-
列表、字典等如果只是修改其中元素的值,可以直接使用全局變量,不需要global聲明
- @不負真人:你這個定位m=5怎么辦?問題是你好像沒排除啊!沒排除這幾個情況!c和r都沒有不會報錯嗎?沒進到這里面,c和r沒有值啊?是沒有c和r吧,這會返回0?
def new_locate(_x_, _y_, _a_, _b_): #上面的版本是學習小鄧同學的定位
'''
新版定位
:param _x_:
:param _y_:
:return:
'''
if M % 3 == 0: #通過向下取整計算出 大的九宮格能分成幾行幾列的小九宮格
_c_ = 3
_r_ = int(M / 3)
elif M % 2 == 0:
_c_ = 2
_r_ = int(M / 2)
_a_ = int(_x_ // _c_ * _c_)
_b_ = int(_y_ // _r_ * _r_)c_:_r_
return _a_, _b_, _c_, _r_ #這里返回 _a_: 當前元素所在的小九宮格 左上角的橫坐標
# _b_: 當前元素所在的小九宮格 左上角的縱坐標
# _c_: 大九宮格被分成了 c行 r列的小九宮格
# _r_:
我:應該會返回0吧,你先試試。表面嘴硬,實則來一波單元測試。
import unittest
from sudoku import new_locate
class MyTestCase(unittest.TestCase):
def test_something(self):
test_num=new_locate(0,0,0,0) #M=3 or 5 or 7
self.assertEqual(test_num,(0,0,0,0) )
if __name__ == '__main__':
unittest.main()
pytest: ZeroDivisionError: integer division or modulo by zero(你除0的樣子真下飯)
改進:
def new_locate(_x_, _y_, _a_, _b_):
'''
新版定位
:param _x_:
:param _y_:
:return:
'''
_c_ = 0 #< - 提前賦值0
_r_ = 0
if 105 % M != 0: 這個里是如果M不等於3、5、7,根據題意不考慮
if M % 3 == 0:
_c_ = 3
_r_ = int(M / 3)
elif M % 2 == 0:
_c_ = 2
_r_ = int(M / 2)
_a_ = int(_x_ // _c_ * _c_)
_b_ = int(_y_ // _r_ * _r_)
return _a_, _b_, _c_, _r_ 這里如果M=3 or 5 or 7,返回 0 0 0 0
- @不負真人:你的不行,你怕是沒看題目要求吧!
對比下我的:
我又開始上網沖浪,查閱資料

python命令行輸入,輸入參數時參數名做參數古被識別為參數做參數名 ???

還是改下吧
NAME_M = sys.argv[1]
NAME_N = sys.argv[3]
N = int(sys.argv[4])
M = int(sys.argv[2])
NAME_IN_FILE = sys.argv[5]
NAME_OUT_FILE = sys.argv[7]
IN_FILE = sys.argv[6]
OUT_FILE = sys.argv[8]
完事兒
參考文獻:https://www.cnblogs.com/ouyangpeng/p/8537616.html
感謝@不負真人大佬的指指點點
大佬:我是fw[1]
后期修改
def dfs(_x_, _y_):
'''
深搜
:param _x_:
:param _y_:
:return:
'''
global F #加入F判斷值 每個九宮格答案唯一 為最先找到得解答情況
if _x_ > M - 1 and F == 0:
disp()
F = 1
elif DATA[_x_][_y_] != 0:
if _y_ == M - 1:
dfs(_x_ + 1, 0)
else:
dfs(_x_, _y_ + 1)
else:
for _i_ in range(1, M + 1):
DATA[_x_][_y_] = _i_
if fun(_x_, _y_) == 1:
if _y_ == M - 1:
dfs(_x_ + 1, 0)
else:
dfs(_x_, _y_ + 1)
DATA[_x_][_y_] = 0
for i in range(N):
if i > 0:
DATA[M * (i - 1):M * i - 1] = DATA[M * i:M * (i + 1)]
print('')
OP.write('\n')
dfs(0, 0)
F = 0 #在解答另外一個九宮格時 先初始化判斷值
各階宮格
3 × 3
4 × 4
5 × 5
6 × 6
7 × 7
8 × 8
9 × 9
自評分
糾錯
_c_ = 0
_r_ = 0
if 105 % M != 0:
if M % 3 == 0:
_r_ = 3 #<-行列混淆了 導致6,8階錯誤
_c_ = int(M / 3)
elif M % 2 == 0:
_r_ = 2
_c_ = int(M / 2)
_a_ = int(_x_ // _c_ * _c_)
_b_ = int(_y_ // _r_ * _r_)
return _a_, _b_, _c_, _r_
改正后:
6 × 6
8 × 8
來自大佬的自嘲,自稱廢物。 ↩︎