简介
井字棋,英文名叫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做人工智能也是比较火热的。