新手學習Python筆記(二)勞拉下棋
新手學習Python,寫第一個Python小遊戲——四連環(重力四子棋)
遊戲規則如下:
棋盤爲8*6
玩家輸入列號與電腦下四子棋,棋會隨着重力下降
勝利方式是一行/一列/左右斜線連四顆棋子
分析:
拆分成了這幾個部分,用自定義函數封裝,便於修改:
·初始化
·棋盤顯示
·玩家輸入
·遊戲運行
·判斷勝利
引用庫:random
第一部分:初始化
def init():
global board #棋盤,二維列表
global rest_num #每一列剩餘棋子數,一維整型列表
global a #先手判定,整型
global reminded_line #未被填滿列的記錄,一維整型列表
global symbol0 #執棋方記錄1,字典
global symbol1 #執棋方記錄2,字典
symbol1 = {
"O": "玩家",
"X": "電腦"
}
symbol0 = {
"X": "玩家",
"O": "電腦"
}
a = random.randint(0,2)
reminded_line = [0,1,2,3,4,5,6,7]
board = [["-"] * 8 for i in range(6)]
rest_num = [6 for i in range(8)]
show(board)
這裏初始化定義了一些之後用得到的變量
第二部分:棋盤顯示
def show(board):
for i in range(6):
for j in range(8):
print(board[i][j],end=" ")
print()
用索引下標的方式遍歷棋盤並打印
第三部分:玩家輸入
def playerInput(rest_num):
while True:
inp = int(input()) - 1 #注意:列表起始於list[0]
if inp in range(0,8): #符合8列
if rest_num[inp] > 0: #該列有空餘
return inp
else:
print("輸入錯誤")
else:
print("輸入錯誤")
輸入用While True循環,直到輸入正確
要判定輸入的列號是否在1-8列內,且該列有空餘!
第四部分:運行
先後手問題在主函數內用 if 判斷初始化內全局變量a來執行不同順序
四子棋的前三個回合不會分出勝負,因此拆分成前三個回合和剩餘回合
這裏可以算多此一舉吧,前三次只是少了判斷勝負
用 round3_0、round4_0 和 round3_1、round4_1 區分
遊戲運行使用for次數循環,勝利提前結束即可
def round3_0():
round_cout = 0 #回合計數
for i in range(3):
round_cout += 1 #回合+1
print("\n===回合數"+str(round_cout)+"===")
print("\n電腦") #常規的面板繪製
#電腦下棋的列號
#這裏用從列表隨機是爲了不會出現該列已滿無法下棋的情況
robot_line = random.sample(reminded_line,1)[0]
#電腦下棋的行號,記得要-1
#因爲重力下落,這裏行號就是空餘數量-1
robot_height = rest_num[robot_line] - 1
#電腦下棋
board[robot_height][robot_line] = "O"
#該列剩餘-1
rest_num[robot_line] -= 1
show(board) #顯示棋盤
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "X"
rest_num[player_line] -= 1
show(board)
def round3_1(): #同上,只是先後手順序改變
round_cout = 0
for i in range(3):
round_cout += 1
print("\n===回合數"+str(round_cout)+"===")
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "O"
rest_num[player_line] -= 1
show(board)
print("\n電腦")
robot_line = random.sample(reminded_line,1)[0]
robot_height = rest_num[robot_line] - 1
board[robot_height][robot_line] = "X"
rest_num[robot_line] -= 1
show(board)
def round4_0():
round_cout = 3 #回合計數
for i in range(3,24): #共48個棋子,24個回合
round_cout += 1
print("\n===回合數"+str(round_cout)+"===")
print("\n電腦")
robot_line = random.sample(reminded_line,1)[0]
robot_height = rest_num[robot_line] - 1
board[robot_height][robot_line] = "O"
rest_num[robot_line] -= 1
#如果該列已滿,則在剩餘列編號列表中移除,排除隨機到該列
if rest_num[robot_line] == 0:
reminded_line.remove(robot_line)
show(board)
#!勝負判定!
IsWinning(board,"O",symbol0)
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "X"
rest_num[player_line] -= 1
if rest_num[robot_line] == 0:
reminded_line.remove(robot_line)
show(board)
IsWinning(board, "X", symbol0)
print("平局!") #最後分不出勝負就是平局
def round4_1():
round_cout = 3
for i in range(3, 24):
round_cout += 1
print("\n===回合數"+str(round_cout)+"===")
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "O"
rest_num[player_line] -= 1
if rest_num[player_line] == 0:
reminded_line.remove(player_line)
show(board)
IsWinning(board, "O", symbol1)
print("\n電腦")
robot_line = random.sample(reminded_line,1)[0]
robot_height = rest_num[robot_line] - 1
board[robot_height][robot_line] = "X"
rest_num[robot_line] -= 1
if rest_num[robot_line] == 0:
reminded_line.remove(robot_line)
show(board)
IsWinning(board, "X", symbol1)
print("平局!")
第五部分:勝利判斷
詳細解釋判定條件
勝利有四種情況:橫4、豎4、左斜4、右斜4
因此繼續封裝成兩種形式:直線、斜線進行判定
因爲左斜和右斜是關於棋盤左右對稱的
這裏board_s就是對稱棋盤
用 [::-1] 進行倒序
傳入三個參數:棋盤、棋子類型(X/O)、執棋方記錄
def IsWinning(board,chess_type,symbol):
rowIsWinning(board,chess_type,symbol)
leftSlashIsWinning(board,chess_type,symbol)
board_s = []
for i in board:
board_s.append(i[::-1]) #左右對稱
leftSlashIsWinning(board_s, chess_type, symbol)
========
直線判定:
def rowIsWinning(board,chess_type,symbol):
#豎4
for line_no in range(8):
for height_no in range(3):
if board[height_no][line_no] == \
board[height_no + 1][line_no] == \
board[height_no + 2][line_no] == \
board[height_no + 3][line_no] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
#橫4
for height_no in range(6):
for line_no in range(5):
if board[height_no][line_no] == \
board[height_no][line_no + 1] == \
board[height_no][line_no + 2] == \
board[height_no][line_no + 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
首先下標索引遍歷每一列
然後在每一列判定是否包含4個相同棋子
每一列得到前三行的棋子,之後再通過列下標不變,行下標遞增獲得四個棋子的座標
橫4的判斷同理
========
難點
斜線判定:
斜線分左斜和右斜,左右是對稱的,因此只用一種方法而將另一種判定換成將棋盤對稱的操作
棋盤也是關於對角線可以對稱的,也可以左右 + 對角線對稱,從而轉換成一種判定方式(棋盤左對角線左方左斜的情況),對棋盤操作統統化成一種
以下以左斜線判定爲例子:
藍色部分無法構成斜線,無需考慮
斜線有一個重要性質:座標行號列號均相差正整數
因此只需要表示出下方綠色區域的棋子座標就可以表示所有斜線:
(還有一種特殊情況)
只要循環表示出綠色區域內的座標 通過行列遞增即可表示斜線:
對於左上區域的座標可以發現:
行號是1-3,而列號是1 ~ 行號
對於右下區域:
行號是4-6,列號是(行號+2) ~ 8
因此可以使用嵌套for循環表示
def leftSlashIsWinning(board,chess_type,symbol):
#表示左上綠色部分
for init_height in range(3):
for init_line in range(init_height + 1):
if board[init_height][init_line] == \
board[init_height + 1][init_line + 1] == \
board[init_height + 2][init_line + 2] == \
board[init_height + 3][init_line + 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
#表示右下綠色部分
for init_height in range(3,6):
for init_line in range(init_height+2,8):
if board[init_height][init_line] == \
board[init_height - 1][init_line - 1] == \
board[init_height - 2][init_line - 2] == \
board[init_height - 3][init_line - 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
#中間特殊情況
for init_height in range(3):
init_line = init_height +1
if board[init_height][init_line] == \
board[init_height + 1][init_line + 1] == \
board[init_height + 2][init_line + 2] == \
board[init_height + 3][init_line + 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
完整代碼:
import random
def init():
global board
global rest_num
global a
global reminded_line
global symbol0
global symbol1
symbol1 = {
"O": "玩家",
"X": "電腦"
}
symbol0 = {
"X": "玩家",
"O": "電腦"
}
a = random.randint(0,2)
reminded_line = [0,1,2,3,4,5,6,7]
board = [["-"] * 8 for i in range(6)]
rest_num = [6 for i in range(8)]
show(board)
def show(board):
for i in range(6):
for j in range(8):
print(board[i][j],end=" ")
print()
def IsWinning(board,chess_type,symbol):
rowIsWinning(board,chess_type,symbol)
leftSlashIsWinning(board,chess_type,symbol)
board_s = []
for i in board:
board_s.append(i[::-1])
leftSlashIsWinning(board_s, chess_type, symbol)
def rowIsWinning(board,chess_type,symbol):
for line_no in range(8):
for height_no in range(3):
if board[height_no][line_no] == \
board[height_no + 1][line_no] == \
board[height_no + 2][line_no] == \
board[height_no + 3][line_no] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
for height_no in range(6):
for line_no in range(5):
if board[height_no][line_no] == \
board[height_no][line_no + 1] == \
board[height_no][line_no + 2] == \
board[height_no][line_no + 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
def leftSlashIsWinning(board,chess_type,symbol):
for init_height in range(3):
for init_line in range(init_height + 1):
if board[init_height][init_line] == \
board[init_height + 1][init_line + 1] == \
board[init_height + 2][init_line + 2] == \
board[init_height + 3][init_line + 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
for init_height in range(3,6):
for init_line in range(init_height+2,8):
if board[init_height][init_line] == \
board[init_height - 1][init_line - 1] == \
board[init_height - 2][init_line - 2] == \
board[init_height - 3][init_line - 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
for init_height in range(3):
init_line = init_height +1
if board[init_height][init_line] == \
board[init_height + 1][init_line + 1] == \
board[init_height + 2][init_line + 2] == \
board[init_height + 3][init_line + 3] == \
chess_type:
print("\n遊戲結束!獲勝的是:" + symbol[chess_type])
exit(0)
def playerInput(rest_num):
while True:
inp = int(input()) - 1
if inp in range(0,8):
if rest_num[inp] > 0:
return inp
else:
print("輸入錯誤")
else:
print("輸入錯誤")
def round3_0():
round_cout = 0
for i in range(3):
round_cout += 1
print("\n===回合數"+str(round_cout)+"===")
print("\n電腦")
robot_line = random.sample(reminded_line,1)[0]
robot_height = rest_num[robot_line] - 1
board[robot_height][robot_line] = "O"
rest_num[robot_line] -= 1
show(board)
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "X"
rest_num[player_line] -= 1
show(board)
def round3_1():
round_cout = 0
for i in range(3):
round_cout += 1
print("\n===回合數"+str(round_cout)+"===")
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "O"
rest_num[player_line] -= 1
show(board)
print("\n電腦")
robot_line = random.sample(reminded_line,1)[0]
robot_height = rest_num[robot_line] - 1
board[robot_height][robot_line] = "X"
rest_num[robot_line] -= 1
show(board)
def round4_0():
round_cout = 3
for i in range(3,24):
round_cout += 1
print("\n===回合數"+str(round_cout)+"===")
print("\n電腦")
robot_line = random.sample(reminded_line,1)[0]
robot_height = rest_num[robot_line] - 1
board[robot_height][robot_line] = "O"
rest_num[robot_line] -= 1
if rest_num[robot_line] == 0:
reminded_line.remove(robot_line)
show(board)
IsWinning(board,"O",symbol0)
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "X"
rest_num[player_line] -= 1
if rest_num[robot_line] == 0:
reminded_line.remove(robot_line)
show(board)
IsWinning(board, "X", symbol0)
print("平局!")
def round4_1():
round_cout = 3
for i in range(3, 24):
round_cout += 1
print("\n===回合數"+str(round_cout)+"===")
print("\n輪到你了:")
player_line = playerInput(rest_num)
player_height = rest_num[player_line] - 1
board[player_height][player_line] = "O"
rest_num[player_line] -= 1
if rest_num[player_line] == 0:
reminded_line.remove(player_line)
show(board)
IsWinning(board, "O", symbol1)
print("\n電腦")
robot_line = random.sample(reminded_line,1)[0]
robot_height = rest_num[robot_line] - 1
board[robot_height][robot_line] = "X"
rest_num[robot_line] -= 1
if rest_num[robot_line] == 0:
reminded_line.remove(robot_line)
show(board)
IsWinning(board, "X", symbol1)
print("平局!")
#程序入口
if __name__ == "__main__":
init()
if a == 1:
round3_1()
round4_1()
else:
round3_0()
round4_0()
遊戲截圖:
完
如果有更好的方法歡迎在評論區指出
謝謝閱讀