简介
井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似,由于棋盘一般不画边框,格线排成井字故得名。游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线,则为获胜。
过程
因为最近在学习Python的实训,学习了接近两周了,感觉Python确实是比较简单的,而且具有丰富的第三方库,(手动点赞),进入正题,一周的基础,当然要进行项目了,作为爱玩游戏的我,当然要从游戏入手,通过制作游戏,可以提升你的思维逻辑,其实写代码更多的是你的逻辑,你的思维。废话不多说先看这个游戏的规则已经在简介说了,首先我们需要绘制棋盘,我们需要知道这个棋盘是多大的我们可以尝试输出:
print("""
0 | 1 | 2
---------
3 | 4 | 5
---------
6 | 7 | 8
""")
这是我们要绘制大致棋盘的样式,这样,我们就可以定义如下参数:
# 全局常量
X = "X"
O = "O"
EMPTY = " "
TIE = "TIE"
NUM_SQUARES = 9
前两个变量就是井字棋的两个棋子,然后定义一个空,一个平局,还有棋盘的位置。
下面就是,我们都要思考的,玩一个游戏,你是和电脑玩(暂时没考虑人人对战)。肯定先询问一下,电脑先手还是玩家先手,所以定义一个询问函数,在这里简单说一下,这个的函数定义,很多地方都可以用得到,方便化结构化管理。
# 询问答案”是“或”否“
def ask_yes_no(question):
response = None
while response not in ('y', 'n'):
response = input(question).lower()
return response
这个就是询问函数返回y/n,下面的函数就是规定落点,棋盘一共九个位置,肯定不能随便下。
# 用户给出指定范围内的一个数字
def ask_number(question, low, high):
response = None
# range(low, high)是左闭右开区间
while response not in range(low, high):
response = int(input(question))
return response
下面就是先手的棋子问题,一般认为先走的为X
# 决定玩家和电脑各执哪种棋子
def pieces():
# 在一个函数内调用另一个函数
go_first = ask_yes_no("是否玩家先走?(y/n):")
if go_first == 'y':
print("玩家先走")
human = X
computer = O
else:
print("电脑先走")
computer = X
human = O
return computer, human
下面就是绘制棋盘逻辑,其实棋盘就是一个数组,存放。
def new_board():
board = []
for i in range(NUM_SQUARES):
board.append(EMPTY)
return board
绘制棋盘:
def display_board(board):
print("\n\t", board[0], "|",
board[1], "|",
board[2])
print("\t", "-" * 9)
print("\t", board[3], "|",
board[4], "|",
board[5])
print("\t", "---------")
print("\t", board[6], "|",
board[7], "|",
board[8])
下面就是下棋的合理性,例如。你再1号位置下了,我肯定不能再下1号位置了。
# 根据当前局面,确保行棋合法
def legal_moves(board):
moves = []
for i in range(NUM_SQUARES):
if board[i] == EMPTY:
moves.append(i)
return moves
胜负状态的判定:
# 判断胜负
# 游戏有四种状态: X获胜,O获胜,平局,正在进行
def winner(board):
# 获胜的8种可能性:一方占据了以下某一行
WAYS_TO_WIN = ((0,1,2),
(3,4,5),
(6,7,8),
(0,3,6),
(1,4,7),
(2,5,8),
(0,4,8),
(2,4,6))
for row in WAYS_TO_WIN:
# WAYS_TO_WIN的某一行都是同一方(O或X)
# 则该方获胜
if board[row[0]] == board[row[1]] \
== board[row[2]] != EMPTY:
the_winner = board[row[0]]
return the_winner
# 如果暂时无人获胜,且棋盘上已经没有空了,则是平局
if EMPTY not in board:
return TIE
# 如果以上结果都未出现,则游戏正在进行,还未结束
return None
然后获取当前棋子合法位置:
def human_move(board, human):
# 获取当前合法落子位置
legal = legal_moves(board)
move = None
while move not in legal:
move = ask_number("在哪里落子?(0-8):",
0, NUM_SQUARES)
if move not in legal:
print("那里不可以")
return move
下一个就是电脑下棋的策略:
def computer_move(board, computer, human):
"""
电脑下棋策略:
1. 如果有一步可以让电脑在本轮获胜,就选那一步
2. 如果有一步可以让玩家在下一轮获胜,就堵那一步
3. 其他情况下,按照方格本身的优先级落子
中间最好,四角次之,边缘最差
"""
BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7)
print("电脑走在:", end=" ")
# 如果电脑能赢,就走那里
for move in legal_moves(board):
# 循环尝试每一合法落子位置
board[move] = computer
# 将该位置从“ ”改为电脑符号
if winner(board) == computer:
print(move)
return move
board[move] = EMPTY
# 电脑赢不了,看有没有会使玩家获胜的位置
for move in legal_moves(board):
board[move] = human
if winner(board) == human:
print(move)
return move
board[move] = EMPTY
# 如果不是以上两种情况,则依照BEST_MOVES的顺序落子
for move in BEST_MOVES:
if move in legal_moves(board):
print(move)
return move
def next_turn(turn):
if turn == O:
return X
else:
return O
最后提示获胜的状态:
def congrat_winner(the_winner, computer, human):
if the_winner != TIE:
print(the_winner, " 获胜!")
else:
print("平局!")
if the_winner == computer:
print("愚蠢的人类")
elif the_winner == human:
print("我会回来的")
elif the_winner == TIE:
print("咱们走着瞧")
然后就是主函数的编写:
def main():
computer, human = pieces() # 人机分配棋子
turn = X # X先走
board = new_board() # 生成一个新棋盘
display_board(board)
# 当胜负未决,winner()返回None
while not winner(board):
if turn == human:
# human_move()返回玩家的落子位置
move = human_move(board, human)
# 将board的落子位置更新为human的棋子
board[move] = human
else:
move = computer_move(board, computer, human)
board[move] = computer
display_board(board)
turn = next_turn(turn)
the_winner = winner(board)
congrat_winner(the_winner, computer, human)
最后运行main函数就OK了
main()
总结
经过简单的小游戏编写测试,把Python的基础巩固好,其实这个游戏,还是牵扯一点点的人工智能, 就是电脑下棋的策略都是最优算法,目前Python做人工智能也是比较火热的。