新手学习Python,写第一个Python小游戏——四连环(重力四子棋)
游戏规则如下:棋盘为8*6
玩家输入列号与电脑下四子棋,棋会随着重力下降
胜利方式是一行一列左右斜线连四颗棋子分析:拆分成了这几个部分,用自定义函数封装,便于修改:
·初始化
·棋盘显示
·玩家输入
·游戏运行
·判断胜利
引用库:rdom第一部分:初始化definit():
globalboard #棋盘,二维列表
globalt_num #每一列剩余棋子数,一维整型列表
globala #先手判定,整型
globalrinded_line #未被填满列的记录,一维整型列表
globalymbol0 #执棋方记录1,字典
globalymbol1 #执棋方记录2,字典ymbol1={
"O":"玩家",
"X":"电脑"
}ymbol0={
"X":"玩家",
"O":"电脑"
}
a=rdom.rdint(0,2)
rinded_line=[0,1,2,3,4,5,6,7]board=[["-"]*8foriinrge(6)]
t_num=[6foriinrge(8)]how(board)这里初始化定义了一些之后用得到的变量第二部分:棋盘显示defhow(board):
foriinrge(6):
forjinrge(8):
rint(board[i][j],end="")
rint()用索引下标的方式遍历棋盘并打印第三部分:玩家输入deflayerInut(t_num):
whileTrue:
in=int(inut())-1 #注意:列表起始于lit[0]
ifininrge(0,8): #符合8列
ift_num[in]>0: #该列有空余
turnin
ele:
rint("输入错误")ele:
rint("输入错误")输入用WhileTrue循环,直到输入正确
要判定输入的列号是否在1-8列内,且该列有空余!第四部分:运行先后手问题在主函数内用if判断初始化内全局变量a来执行不同顺序
四子棋的前三个回合不会分出胜负,因此拆分成前三个回合和剩余回合
这里可以算多此一举吧,前三次只是少了判断胜负
用round3_0、round4_0和round3_1、round4_1区分
游戏运行使用for次数循环,胜利提前结束即可
defround3_0():
round_cout=0 #回合计数foriinrge(3):
round_cout+=1 #回合+1
rint("n===回合数"+tr(round_cout)+"===")rint("n电脑") #常规的面板绘制
#电脑下棋的列号
#这里用从列表随机是为了不会出现该列已满无法下棋的情况
robot_line=rdom.amle(rinded_line,1)[0]
#电脑下棋的行号,记得要-1
#因为重力下落,这里行号就是空余数量-1
robot_height=t_num[robot_line]-1 #电脑下棋board[robot_height][robot_line]="O"
#该列剩余-1
t_num[robot_line]-=1how(board) #显示棋盘rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="X"t_num[layer_line]-=1how(board)defround3_1(): #同上,只是先后手顺序改变
round_cout=0foriinrge(3):
round_cout+=1
rint("n===回合数"+tr(round_cout)+"===")rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="O"t_num[layer_line]-=1how(board)rint("n电脑")robot_line=rdom.amle(rinded_line,1)[0]
robot_height=t_num[robot_line]-1board[robot_height][robot_line]="X"t_num[robot_line]-=1how(board)defround4_0():
round_cout=3 #回合计数
foriinrge(3,24): #共48个棋子,24个回合
round_cout+=1
rint("n===回合数"+tr(round_cout)+"===")rint("n电脑")robot_line=rdom.amle(rinded_line,1)[0]
robot_height=t_num[robot_line]-1board[robot_height][robot_line]="O"t_num[robot_line]-=1
#如果该列已满,则在剩余列编号列表中移除,排除随机到该列
ift_num[robot_line]==0:
rinded_line.rove(robot_line)how(board)
#!胜负判定!
IWinning(board,"O",ymbol0)rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="X"t_num[layer_line]-=1ift_num[robot_line]==0:
rinded_line.rove(robot_line)how(board)IWinning(board,"X",ymbol0)rint("平局!") #最后分不出胜负就是平局defround4_1():
round_cout=3
foriinrge(3,24):
round_cout+=1
rint("n===回合数"+tr(round_cout)+"===")rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="O"t_num[layer_line]-=1ift_num[layer_line]==0:
rinded_line.rove(layer_line)how(board)IWinning(board,"O",ymbol1)rint("n电脑")robot_line=rdom.amle(rinded_line,1)[0]
robot_height=t_num[robot_line]-1board[robot_height][robot_line]="X"t_num[robot_line]-=1ift_num[robot_line]==0:
rinded_line.rove(robot_line)how(board)IWinning(board,"X",ymbol1)rint("平局!")第五部分:胜利判断
(包含详细解释判定条件)胜利有四种情况:横4、竖4、左斜4、右斜4
因此继续封装成两种形式:直线、斜线进行判定
因为左斜和右斜是关于棋盘左右对称的
这里board_就是对称棋盘
用[::-1]进行倒序
传入三个参数:棋盘、棋子类型(XO)、执棋方记录
defIWinning(board,che_tye,ymbol):
rowIWinning(board,che_tye,ymbol)leftSlahIWinning(board,che_tye,ymbol)board_=[]
foriinboard:
board_.aend(i[::-1]) #左右对称leftSlahIWinning(board_,che_tye,ymbol)========
直线判定:
defrowIWinning(board,che_tye,ymbol):
#竖4
forline_noinrge(8):
forheight_noinrge(3):
ifboard[height_no][line_no]==
board[height_no+1][line_no]==
board[height_no+2][line_no]==
board[height_no+3][line_no]==
che_tye:
rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)
#横4
forheight_noinrge(6):
forline_noinrge(5):
ifboard[height_no][line_no]==
board[height_no][line_no+1]==
board[height_no][line_no+2]==
board[height_no][line_no+3]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)首先下标索引遍历每一列
然后在每一列判定是否包含4个相同棋子
每一列得到前三行的棋子,之后再通过列下标不变,行下标递增获得四个棋子的坐标
横4的判断同理========
难点
斜线判定:
斜线分左斜和右斜,左右是对称的,因此只用一种方法而将另一种判定换成将棋盘对称的操作
棋盘也是关于对角线可以对称的,也可以左右+对角线对称,从而转换成一种判定方式(棋盘左对角线左方左斜的情况),对棋盘操作统统化成一种
以下以左斜线判定为例子:蓝色部分无法构成斜线,无需考虑
斜线有一个重要性质:坐标行号列号均相差正整数
因此只需要表示出下方绿色区域的棋子坐标就可以表示所有斜线:
(还有一种特殊情况)只要循环表示出绿色区域内的坐标通过行列递增即可表示斜线:对于左上区域的坐标可以发现:
行号是1-3,而列号是1~行号
对于右下区域:
行号是4-6,列号是(行号+2)~8
因此可以使用嵌套for循环表示
defleftSlahIWinning(board,che_tye,ymbol):
#表示左上绿色部分
forinit_heightinrge(3):
forinit_lineinrge(init_height+1):
ifboard[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]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)
#表示右下绿色部分
forinit_heightinrge(3,6):
forinit_lineinrge(init_height+2,8):
ifboard[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]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)
#中间特殊情况
forinit_heightinrge(3):
init_line=init_height+1
ifboard[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]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)
完整代码:imortrdomdefinit():
globalboard
globalt_num
globala
globalrinded_line
globalymbol0
globalymbol1ymbol1={
"O":"玩家",
"X":"电脑"
}ymbol0={
"X":"玩家",
"O":"电脑"
}
a=rdom.rdint(0,2)
rinded_line=[0,1,2,3,4,5,6,7]board=[["-"]*8foriinrge(6)]
t_num=[6foriinrge(8)]how(board)defhow(board):
foriinrge(6):
forjinrge(8):
rint(board[i][j],end="")
rint()defIWinning(board,che_tye,ymbol):
rowIWinning(board,che_tye,ymbol)leftSlahIWinning(board,che_tye,ymbol)board_=[]
foriinboard:
board_.aend(i[::-1])leftSlahIWinning(board_,che_tye,ymbol)defrowIWinning(board,che_tye,ymbol):
forline_noinrge(8):
forheight_noinrge(3):
ifboard[height_no][line_no]==
board[height_no+1][line_no]==
board[height_no+2][line_no]==
board[height_no+3][line_no]==
che_tye:
rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)forheight_noinrge(6):
forline_noinrge(5):
ifboard[height_no][line_no]==
board[height_no][line_no+1]==
board[height_no][line_no+2]==
board[height_no][line_no+3]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)defleftSlahIWinning(board,che_tye,ymbol):forinit_heightinrge(3):
forinit_lineinrge(init_height+1):
ifboard[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]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)forinit_heightinrge(3,6):
forinit_lineinrge(init_height+2,8):
ifboard[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]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)forinit_heightinrge(3):
init_line=init_height+1
ifboard[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]==
che_tye:rint("n游戏结束!获胜的是:"+ymbol[che_tye])
exit(0)deflayerInut(t_num):
whileTrue:
in=int(inut())-1
ifininrge(0,8):
ift_num[in]>0:
turnin
ele:
rint("输入错误")ele:
rint("输入错误")defround3_0():
round_cout=0foriinrge(3):
round_cout+=1
rint("n===回合数"+tr(round_cout)+"===")rint("n电脑")robot_line=rdom.amle(rinded_line,1)[0]
robot_height=t_num[robot_line]-1board[robot_height][robot_line]="O"t_num[robot_line]-=1how(board)rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="X"t_num[layer_line]-=1how(board)defround3_1():
round_cout=0foriinrge(3):
round_cout+=1
rint("n===回合数"+tr(round_cout)+"===")rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="O"t_num[layer_line]-=1how(board)rint("n电脑")robot_line=rdom.amle(rinded_line,1)[0]
robot_height=t_num[robot_line]-1board[robot_height][robot_line]="X"t_num[robot_line]-=1how(board)defround4_0():
round_cout=3
foriinrge(3,24):
round_cout+=1
rint("n===回合数"+tr(round_cout)+"===")rint("n电脑")robot_line=rdom.amle(rinded_line,1)[0]
robot_height=t_num[robot_line]-1board[robot_height][robot_line]="O"t_num[robot_line]-=1ift_num[robot_line]==0:
rinded_line.rove(robot_line)how(board)IWinning(board,"O",ymbol0)rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="X"t_num[layer_line]-=1ift_num[robot_line]==0:
rinded_line.rove(robot_line)how(board)IWinning(board,"X",ymbol0)rint("平局!")defround4_1():
round_cout=3
foriinrge(3,24):
round_cout+=1
rint("n===回合数"+tr(round_cout)+"===")rint("n轮到你了:")layer_line=layerInut(t_num)
layer_height=t_num[layer_line]-1board[layer_height][layer_line]="O"t_num[layer_line]-=1ift_num[layer_line]==0:
rinded_line.rove(layer_line)how(board)IWinning(board,"O",ymbol1)rint("n电脑")robot_line=rdom.amle(rinded_line,1)[0]
robot_height=t_num[robot_line]-1board[robot_height][robot_line]="X"t_num[robot_line]-=1ift_num[robot_line]==0:
rinded_line.rove(robot_line)how(board)IWinning(board,"X",ymbol1)rint("平局!")#程序入口
if__name__=="__main__":
init()ifa==1:
round3_1()
round4_1()
ele:
round3_0()
round4_0()