python实现井字棋小游戏,简单易学

---利用启发式搜索策略模拟机器人进行井字棋对弈---

文章目录


前言

实现井字棋人机对弈小游戏编程:

例如:python作为一种简单过程化的高级语言,具备很好的性能,用python做一个小游戏既能提升自己对python的掌握能力,又能为大家的学习带来更多乐趣。


以下是本篇文章正文内容

一、怎样实现井字棋的人机对弈,原理,玩法?

人机对弈,简单来说就是电脑通过分析棋局,得到胜算最大的落棋点,然后与人对弈,此程序采用的是类似迪杰斯特拉算法求解最短路径来求得最优解,也类似于人工智能方向的启发式搜索策略。在面对任何一种棋盘形势时,通过寻找棋子的可落脚点的各种可能,并通过每种可能状态下的可赢的可能性来寻找棋子最好的落脚点。

原理:井字棋一共有八种赢的方式,分别是横三种竖三种和对角线两种,定义一个列表可以用来储存棋盘上的这八种路线,用line来表示,那么每发现line中的一条边不可能行得通,line中就会少一条边,通过分析棋子在不同落脚点时line中能赢的可能情况总和即可得出最优解,在对弈中除了要考虑最优解以外还需分析最优解中的最优解,以及两种情况:一步即赢时优先一步即赢,在不能一步即赢的情况下,要优先考虑拦截对手,其次再考虑其他情况中的最优解。

玩法:利用电脑键盘右方小键盘0-9输入即可,与棋盘上一一对应

此程序仅需要用到内置库:time,copy.

二、使用步骤

1.引入库,创建一个类,并构造初始函数;

代码如下:

import copy
import time
class Tic_toc_tae():
    def __init__(self):
        self.chessboard=[[],[],[]]#存放棋盘
        self.line=[[],[],[],[],[],[],[],[]]#存放各条边,包括斜着的边
        self.player_plot='x'#玩家用x号
        self.rebot_plot='o'#电脑用o号
        self.n=0
        self.STOP=False#决定整个游戏是否继续

2.向类中增加初始化自定义函数

代码如下:

def initialation(self):
    for i in range(len(self.chessboard)):#初始化棋盘
        self.chessboard[i]=[' ',' ',' ']
    for j in range(3):#初始化记录各条能赢的边
        self.line[j]=self.chessboard[j]
        self.line[j+3]=[self.chessboard[j][0],self.chessboard[j][1],self.chessboard[j][2]]
    self.line[6]=[self.chessboard[0][0],self.chessboard[1][1],self.chessboard[2][2]]
    self.line[7]=[self.chessboard[2][0],self.chessboard[1][1],self.chessboard[2][2]]
    return self.chessboard
def get_now_line(self,chessboard):#方便后续调用
    line=[[],[],[],[],[],[],[],[]]
    for j in range(3):
        line[j]=copy.deepcopy(chessboard[j])
        line[j+3]=copy.deepcopy([chessboard[0][j],chessboard[1][j],chessboard[2][j]])
    line[6]=copy.deepcopy([chessboard[0][0],chessboard[1][1],chessboard[2][2]])
    line[7]=copy.deepcopy([chessboard[2][0],chessboard[1][1],chessboard[0][2]])
    return line

3.向类中增加玩家输入功能和显示功能:

代码如下(注意到copy内置函数的使用,由于列表直接赋值会导致地址错误,所以不得不使用copy函数让一个列表可以多次使用):

def change_chessboard(self,keys1):#这里是主要的下棋部分,后面都要引用到
    plot=self.player_plot
    chessboard=copy.deepcopy(self.chessboard)#得到目前的棋盘
    STOP=0
    n=0
    body=True
    key=False
    while(True and STOP==0):
        if keys1==0:
            try:
                n=int(input("从小键盘输入对应位置\n"))
            except(ValueError):
                print("请重新输入")
            else:
                STOP=1
        if keys1!=0:
            n=keys1
            body=False
        if n>0 and n<=3:
            if chessboard[2][n-1]==plot or chessboard[2][n-1]==self.rebot_plot:
                print("这里不能再下")
                continue
            if body==False:
                chessboard[2][n-1]=self.rebot_plot
            else:
                chessboard[2][n-1]=plot
            key=True
            STOP=1
        elif n>=4 and n<=6:
            if chessboard[1][n-4]==plot or chessboard[1][n-4]==self.rebot_plot:
                print("这里不能再下")
                continue
            if body==False:
                chessboard[1][n-4]=self.rebot_plot
            else:
                chessboard[1][n-4]=plot
            key=True
            STOP=1
        elif n>=7 and n<=9:
            if chessboard[0][n-7]==plot or chessboard[0][n-7]==self.rebot_plot:
                print("这里不能再下")
                continue
            if body==False:
                chessboard[0][n-7]=self.rebot_plot
            else:
                chessboard[0][n-7]=plot
            key=True
            STOP=1
    #if key==True:
    #    print("操作成功")
    return chessboard
def show_chessboard(self):#输出功能,把棋盘可视化出来
    for i in self.chessboard:
        for j in i:
            print("|"+j,end='|')
        print()

4.向类中增加机器人功能:

机器人这块主要分三部分:

1,主函数

2,搜索寻求最优可能

3,分析得出最优解

def rebot(self):#主函数
    if self.STOP==None:#STOP约束,方便停止游戏
        try:
            x,y=self.rebot_analyze()
            self.chessboard[x][y] = self.rebot_plot
        except(TypeError,UnboundLocalError):#输入非0-9时报错情况处理
            print("-------")
def rebot_get_line(self,Chessboard):#分析一个落棋点的可行度
    self.line=copy.deepcopy(self.get_now_line(Chessboard))
    line=0
    for i in self.line:
        n=0
        prevent=0
        for j in i:
           if j==self.player_plot:
               #self.line.remove(i)
               prevent+=1
           if j==self.rebot_plot:
               n+=1
        if n==3:#在一步能赢时,优先一步取得胜利
            line+=300
        if prevent==2 and n==1:#在一步不能赢时,优先拦截对方
            line+=200
            n=0
        if n==1:
            line+=1
        if n==2:
            line+=50
    return line
def rebot_analyze(self):#分析得出最优解,可以说是主程序
    all_situation=[]
    Chessboard=copy.deepcopy(self.chessboard)
    for i in range(len(Chessboard)):
        for j in range(len(Chessboard[i])):
            if Chessboard[i][j]!=self.player_plot and Chessboard[i][j]!=self.rebot_plot:
                Chessboard=self.change_chessboard(3*(2-i)+j+1)
                n=self.rebot_get_line(Chessboard)
                all_situation.append([n,i,j])
    if all_situation==[]:
        print("游戏结束,平局")
        self.STOP=True
        return self.STOP
    all_situation2=[]
    for i in all_situation:
        all_situation2.append(i[0])
    max_n=0
    for j in range(len(all_situation2)):
        if all_situation2[j]==max(all_situation2):
            max_n=j
    x=all_situation[max_n][1]
    y=all_situation[max_n][2]
    return x,y

5.向类中增加分析棋盘的功能

代码如下(及时分析棋盘,得出胜负):

def referee(self):
    if self.STOP==None:
        line=copy.deepcopy(self.get_now_line(self.chessboard))
        rebot=player=0
        n=0
        for i in line:
            rebot=player=0
            for k in i:
                if k==self.rebot_plot:
                    rebot+=1
                if k==self.player_plot:
                    player+=1
            if rebot==3:
                print("------机器人获胜------")
                return True
            if player==3:
                print("------玩家获胜------")
                return True

6,改善整个类,并封装,从外部调用

代码如下:

def run(self):#使用run函数作为主函数,调用整个程序的自定义函数
    print("---|井字棋|---")
    print("->人机对弈-1.0版本-503<-")
    print("[x 为玩家,o 为电脑]")
    print()
    while(self.STOP==False):
        self.initialation()
        self.show_chessboard()
        while(self.STOP!=True):
            self.chessboard=self.change_chessboard(0)
            self.STOP=self.referee()
            print("机器思考中")
            time.sleep(1)
            self.rebot()
            if self.STOP!=True:
                self.STOP=self.referee()
            self.show_chessboard()
        print("->是否再来一局?")
        anything=input("->按0退出,按其他键再来一局\n")
        if anything=='0':
            self.STOP=True
        else:
            self.STOP=False
tic_toc_tae=Tic_toc_tae()
tic_toc_tae.run()

游戏界面:

总结

希望大家玩的开心,由于作者水平有限,文章可能会出现谬误,欢迎大佬指正。
------------------------------------------------------------

  • 12
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,以下是一个简单Python AI 井字棋游戏的代码: ```python import random def draw_board(board): # This function prints out the board that it was passed. # "board" is a list of 10 strings representing the board (ignore index 0) print(' | |') print(' ' + board[7] + ' | ' + board[8] + ' | ' + board[9]) print(' | |') print('-----------') print(' | |') print(' ' + board[4] + ' | ' + board[5] + ' | ' + board[6]) print(' | |') print('-----------') print(' | |') print(' ' + board[1] + ' | ' + board[2] + ' | ' + board[3]) print(' | |') def input_player_letter(): # Lets the player type which letter they want to be. # Returns a list with the player's letter as the first item, and the AI's letter as the second. letter = '' while not (letter == 'X' or letter == 'O'): print('Do you want to be X or O?') letter = input().upper() # the first element in the tuple is the player's letter, the second is the AI's letter. if letter == 'X': return ['X', 'O'] else: return ['O', 'X'] def who_goes_first(): # Randomly choose the player who goes first. if random.randint(0, 1) == 0: return 'AI' else: return 'player' def make_move(board, letter, move): board[move] = letter def is_winner(bo, le): # Given a board and a player's letter, this function returns True if that player has won. # We use bo instead of board and le instead of letter so we don't have to type as much. return ((bo[7] == le and bo[8] == le and bo[9] == le) or # across the top (bo[4] == le and bo[5] == le and bo[6] == le) or # across the middle (bo[1] == le and bo[2] == le and bo[3] == le) or # across the bottom (bo[7] == le and bo[4] == le and bo[1] == le) or # down the left side (bo[8] == le and bo[5] == le and bo[2] == le) or # down the middle (bo[9] == le and bo[6] == le and bo[3] == le) or # down the right side (bo[7] == le and bo[5] == le and bo[3] == le) or # diagonal (bo[9] == le and bo[5] == le and bo[1] == le)) # diagonal def get_board_copy(board): # Make a duplicate of the board list and return it the duplicate. dupe_board = [] for i in board: dupe_board.append(i) return dupe_board def is_space_free(board, move): # Return true if the passed move is free on the passed board. return board[move] == ' ' def get_player_move(board): # Let the player type in their move. move = ' ' while move not in '1 2 3 4 5 6 7 8 9'.split() or not is_space_free(board, int(move)): print('What is your next move? (1-9)') move = input() return int(move) def choose_random_move_from_list(board, movesList): # Returns a valid move from the passed list on the passed board. # Returns None if there is no valid move. possibleMoves = [] for i in movesList: if is_space_free(board, i): possibleMoves.append(i) if len(possibleMoves) != 0: return random.choice(possibleMoves) else: return None def get_ai_move(board, ai_letter): # Given a board and the computer's letter, determine where to move and return that move. if ai_letter == 'X': player_letter = 'O' else: player_letter = 'X' # Here is our algorithm for our Tic Tac Toe AI: # First, check if we can win in the next move for i in range(1, 10): copy = get_board_copy(board) if is_space_free(copy, i): make_move(copy, ai_letter, i) if is_winner(copy, ai_letter): return i # Check if the player could win on their next move, and block them. for i in range(1, 10): copy = get_board_copy(board) if is_space_free(copy, i): make_move(copy, player_letter, i) if is_winner(copy, player_letter): return i # Try to take one of the corners, if they are free. move = choose_random_move_from_list(board, [1, 3, 7, 9]) if move != None: return move # Try to take the center, if it is free. if is_space_free(board, 5): return 5 # Move on one of the sides. return choose_random_move_from_list(board, [2, 4, 6, 8]) def is_board_full(board): # Return True if every space on the board has been taken. Otherwise return False. for i in range(1, 10): if is_space_free(board, i): return False return True print('Welcome to AI Tic Tac Toe!') while True: # Reset the board the_board = [' '] * 10 player_letter, ai_letter = input_player_letter() turn = who_goes_first() print('The ' + turn + ' will go first.') game_is_playing = True while game_is_playing: if turn == 'player': # Player's turn. draw_board(the_board) move = get_player_move(the_board) make_move(the_board, player_letter, move) if is_winner(the_board, player_letter): draw_board(the_board) print('Hooray! You have won the game!') game_is_playing = False else: if is_board_full(the_board): draw_board(the_board) print('The game is a tie!') break else: turn = 'AI' else: # AI's turn. move = get_ai_move(the_board, ai_letter) make_move(the_board, ai_letter, move) if is_winner(the_board, ai_letter): draw_board(the_board) print('The AI has beaten you! You lose.') game_is_playing = False else: if is_board_full(the_board): draw_board(the_board) print('The game is a tie!') break else: turn = 'player' print('Do you want to play again? (yes or no)') if not input().lower().startswith('y'): break ``` 希望这个代码能够帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值