你相信吗?用ChatGPT写井字棋游戏仅需几分钟

news2024/11/17 23:57:54

井字棋

我们先实现一个最基本的使用控制台交互的井字棋游戏。
在这里插入图片描述

为了保持代码整洁,方便后续扩展,我们使用类Board来实现棋盘。除了常规的初始化方法__init__和字符串方法__str__,我们还要判断游戏的胜负、棋子位置的合理性。

main中,我们在while循环中实现两个玩家的交替下棋,直到一方胜利或棋盘满了为止。

代码整体比较简单,只是在判断胜利时需要处理好多个条件。

class Board:
    def __init__(self, size=3):
        self.board = [['_' for j in range(size)] for i in range(size)]
        self.size = size

    def __str__(self):
        res = ""
        for row in self.board:
            temp_row = ""
            for col in row:
                temp_row = temp_row + col + '\t'
            res += str(temp_row) + "\n"
        return res

    def display(self):
        print(self)

    def can_set(self, row, col):
        return 0 <= row < self.size and 0 <= col < self.size and self.board[row][col] == '_'

    def set_board(self, row, col, mark):
        if self.can_set(row, col):
            self.board[row][col] = mark
        else:
            print("Invalid input...,")

    def check_win(self):
        for row in self.board:
            if all(x == 'X' for x in row):
                return "Player 1 wins"
            elif all(x == 'O' for x in row):
                return "Player 2 wins"

        for col in range(self.size):
            if all(self.board[row][col] == 'X' for row in range(self.size)):
                return "Player 1 wins"
            elif all(self.board[row][col] == 'O' for row in range(self.size)):
                return "Player 2 wins"

        # Diagonal
        if all(self.board[i][i] == 'X' for i in range(self.size)) or all(self.board[i][self.size-1-i] == 'X' for i in range(self.size)):
            return "Player 1 wins"
        elif all(self.board[i][i] == 'O' for i in range(self.size)) or all(self.board[i][self.size-1-i] == 'O' for i in range(self.size)):
            return "Player 2 wins"

        return "No one wins"

    def is_full(self):
        return not any(self.board[i][j] == '_' for i in range(self.size) for j in range(self.size))


if __name__ == '__main__':
    size = int(input("Please input the size of the board: "))
    board = Board(size)
    board.display()
    # player 1:X  player 2:  O
    marks = ['X', 'O']
    player = 0
    while not board.is_full() and board.check_win() == "No one wins":
        index = input(f"Please player {player+1} input coordinates (row, col): ")
        try:
            row, col = index.split(',')
            row, col = int(row)-1, int(col)-1
        except ValueError:
            print("Invalid input. Please input two integers separated by a comma.")
            continue
        if board.can_set(row, col):
            board.set_board(row, col, marks[player])
        else:
            print("This cell is already occupied. Please choose another one.")
            continue
        player = (player + 1) % 2
        board.display()

    print(board.check_win())

使用tkinter创建图形界面

在这个程序中,使用了tkinter模块来创建窗口和按钮。每个按钮都由Button类创建,并通过grid()方法来定位。当按钮被点击时,clicked()方法被调用,将其设置为当前玩家的标记,并切换到下一个玩家。每次下棋后,程序会检查游戏是否已结束。如果游戏结束,程序会调用show_winner()方法来显示获胜者或平局信息,并禁用所有按钮。

import tkinter as tk

class TicTacToeGUI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Tic Tac Toe")

        # 创建9个按钮
        self.buttons = []
        for i in range(3):
            row = []
            for j in range(3):
                button = tk.Button(self.root, text="", font=("Helvetica", 24), width=5, height=2, command=lambda row=i, col=j: self.clicked(row, col))
                button.grid(row=i, column=j)
                row.append(button)
            self.buttons.append(row)

        self.current_player = "X"
        self.board = [
            ["-", "-", "-"],
            ["-", "-", "-"],
            ["-", "-", "-"]
        ]

    def clicked(self, row, col):
        """
        当一个按钮被点击时,将其设置为当前玩家的标记,并切换到下一个玩家。
        """
        if self.board[row][col] == "-":
            self.buttons[row][col].config(text=self.current_player)
            self.board[row][col] = self.current_player
            if self.current_player == "X":
                self.current_player = "O"
            else:
                self.current_player = "X"
            self.check_game_over()

    def check_game_over(self):
        """
        检查游戏是否已结束
        """
        for i in range(3):
            # 检查行
            if self.board[i][0] != "-" and self.board[i][0] == self.board[i][1] and self.board[i][1] == self.board[i][2]:
                self.show_winner(self.board[i][0])
                return
            # 检查列
            if self.board[0][i] != "-" and self.board[0][i] == self.board[1][i] and self.board[1][i] == self.board[2][i]:
                self.show_winner(self.board[0][i])
                return
        # 检查对角线
        if self.board[0][0] != "-" and self.board[0][0] == self.board[1][1] and self.board[1][1] == self.board[2][2]:
            self.show_winner(self.board[0][0])
            return
        if self.board[0][2] != "-" and self.board[0][2] == self.board[1][1] and self.board[1][1] == self.board[2][0]:
            self.show_winner(self.board[0][2])
            return
        # 检查是否有空格
        for row in self.board:
            for cell in row:
                if cell == "-":
                    return
        # 如果没有空格,平局
        self.show_winner("Tie")

    def show_winner(self, winner):
        """
        显示获胜者或平局信息,并禁用所有按钮。
        """
        if winner == "Tie":
            message = "It's a tie!"
        else:
            message = f"Player {winner} wins!"
        for row in self.buttons:
            for button in row:
                button.config(state="disabled")
        self.root.title(message)

    def start(self):
        """
        开始游戏。
        """
        self.root.mainloop()

# 运行游戏
game = TicTacToeGUI()
game.start()

人机对战版

这是一个井字游戏的 Python 代码,分别有三个类:BoardAIPlayerGame

Board
这个类代表了游戏的棋盘,有以下方法:

  • __init__(self, size=3):构造函数,初始化棋盘为给定大小的二维列表,初始值为 ‘_’。
  • __str__(self):返回当前棋盘的字符串表示形式。
  • display(self):打印当前棋盘的字符串表示形式。
  • can_set(self, row, col):判断给定位置能否放置棋子。
  • set_board(self, row, col, mark):将给定位置放置给定的标记(‘X’ 或 ‘O’)。
  • check_win(self):判断当前棋局是否已分出胜负,返回 “Player 1 wins”、“Player 2 wins” 或 “No one wins”。
  • is_full(self):判断当前棋盘是否已满。
  • copy(self):返回当前棋盘的副本。

AIPlayer
这个类代表了游戏中的 AI 玩家,有以下方法:

  • __init__(self, mark):构造函数,初始化 AI 玩家的标记(‘X’ 或 ‘O’)。
  • get_best_move(self, board):计算当前 AI 玩家应该下的最佳位置。
  • minimax(self, board, is_maximizing, alpha, beta):计算给定棋盘状态下当前玩家的最大(或最小)得分。

Game
这个类代表了游戏本身,有以下方法:

  • __init__(self, size=3, ai_mode=False):构造函数,初始化游戏的棋盘大小和是否启用 AI 模式。
  • start(self):开始游戏。
    在 start 方法中,游戏会循环进行,直到棋盘已满或有一方获胜。每次循环,根据当前玩家是否是 AI,分别提示玩家输入位置或计算 AI 玩家应该下的位置,然后更新棋盘,交换当前玩家。
class Board:
    def __init__(self, size=3):
        self.board = [['_' for j in range(size)] for i in range(size)]
        self.size = size

    def __str__(self):
        res = ""
        for row in self.board:
            temp_row = ""
            for col in row:
                temp_row = temp_row + col + '\t'
            res += str(temp_row) + "\n"
        return res

    def display(self):
        print(self)

    def can_set(self, row, col):
        return 0 <= row < self.size and 0 <= col < self.size and self.board[row][col] == '_'

    def set_board(self, row, col, mark):
        if self.can_set(row, col):
            self.board[row][col] = mark
        else:
            print("Invalid input...,")

    def check_win(self):
        for row in self.board:
            if all(x == 'X' for x in row):
                return "Player 1 wins"
            elif all(x == 'O' for x in row):
                return "Player 2 wins"

        for col in range(self.size):
            if all(self.board[row][col] == 'X' for row in range(self.size)):
                return "Player 1 wins"
            elif all(self.board[row][col] == 'O' for row in range(self.size)):
                return "Player 2 wins"

        # Diagonal
        if all(self.board[i][i] == 'X' for i in range(self.size)) or all(
                self.board[i][self.size - 1 - i] == 'X' for i in range(self.size)):
            return "Player 1 wins"
        elif all(self.board[i][i] == 'O' for i in range(self.size)) or all(
                self.board[i][self.size - 1 - i] == 'O' for i in range(self.size)):
            return "Player 2 wins"

        return "No one wins"

    def is_full(self):
        return not any(self.board[i][j] == '_' for i in range(self.size) for j in range(self.size))

    def copy(self):
        new_board = Board(self.size)
        for i in range(self.size):
            for j in range(self.size):
                new_board.board[i][j] = self.board[i][j]
        return new_board

class AIPlayer:
    def __init__(self, mark):
        self.mark = mark

    def get_best_move(self, board):
        best_score = -1000
        best_move = None

        for row in range(board.size):
            for col in range(board.size):
                if board.can_set(row, col):
                    board_copy = board.copy()
                    board_copy.set_board(row, col, self.mark)
                    score = self.minimax(board_copy, False, -1000, 1000)
                    if score > best_score:
                        best_score = score
                        best_move = (row, col)

        return best_move

    def minimax(self, board, is_maximizing, alpha, beta):
        result = board.check_win()
        if result == "Player 1 wins":
            return -1
        elif result == "Player 2 wins":
            return 1
        elif board.is_full():
            return 0

        if is_maximizing:
            best_score = -1000
            for row in range(board.size):
                for col in range(board.size):
                    if board.can_set(row, col):
                        board_copy = board.copy()
                        board_copy.set_board(row, col, 'O')
                        score = self.minimax(board_copy, False, alpha, beta)
                        best_score = max(best_score, score)
                        alpha = max(alpha, best_score)
                        if beta <= alpha:
                            break
            return best_score

        else:
            best_score = 1000
            for row in range(board.size):
                for col in range(board.size):
                    if board.can_set(row, col):
                        board_copy = board.copy()
                        board_copy.set_board(row, col, 'X')
                        score = self.minimax(board_copy, True, alpha, beta)
                        best_score = min(best_score, score)
                        beta = min(beta, best_score)
                        if beta <= alpha:
                            break
            return best_score


class Game:
    def __init__(self, size=3, ai_mode=False):
        self.board = Board(size)
        self.ai_mode = ai_mode
        self.player_marks = ['X', 'O']
        self.player_turn = 0

        if ai_mode:
            self.ai_player = AIPlayer(self.player_marks[1])

    def start(self):
        print("Starting the game...")
        self.board.display()

        while not self.board.is_full() and self.board.check_win() == "No one wins":
            current_player_mark = self.player_marks[self.player_turn]
            if self.player_turn == 1 and self.ai_mode:
                print("AI is thinking...")
                row, col = self.ai_player.get_best_move(self.board)
                print(f"AI placed {current_player_mark} at row {row + 1}, col {col + 1}")
                self.board.set_board(row, col, current_player_mark)
            else:
                index = input(f"Please player {self.player_turn + 1} input coordinates (row, col): ")
                try:
                    row, col = index.split(',')
                    row, col = int(row) - 1, int(col) - 1
                except ValueError:
                    print("Invalid input. Please input two integers separated by a comma.")
                    continue
                if not self.board.can_set(row, col):
                    print("This cell is already occupied. Please choose another one.")
                    continue
                self.board.set_board(row, col, current_player_mark)

            self.board.display()
            self.player_turn = (self.player_turn + 1) % 2

        print(self.board.check_win())


if __name__ == '__main__':
    game = Game(size=3, ai_mode=True)
    game.start()

说明

第二部分(人机对战)全部由ChatGPT生成(中间经过多次调整),第一部分的代码是ChatGPT在我的代码基础上优化后的结果。
对于简单的问题,ChatGPT通常能给出完美的回答。但对于复杂问题则相对差一些,需要多次修改。此外,ChatGPT无法保证内容的正确性,有时候会给出似是而非的误导性回答。值得一提的是,ChatGPT对代码的理解能力特别强,能很好地给自己的代码加注释(大概是因为代码比较规范,流程相对固定,比较容易学习)。

ChatGPT能提高写代码及其它文字的效率,可以用来

  • 注释代码
  • 写一段简单函数
  • 提供灵感(比如起标题)
  • 写格式比较固定的文字(邮件等)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

但是,ChatGPT对事实类问题的回答比较离谱:
在这里插入图片描述

在这里插入图片描述

更多ChatGPT的案例可以看看:
ChatGPT评测观察之对话能力|语义理解较准,尚难以摆脱知识整合和逻辑推理困境 https://mp.weixin.qq.com/s/ZjZgMZIXiD966hcFua_gew

ChatGPT是一种生成式预训练transformer(generative pre-trained transformer, GPT),使用有监督学习和强化学习对GPT-3.5进行微调。在两种方法中,人类训练者都用于提高模型的性能。在有监督学习中,模型被提供了对话,训练者在其中扮演了用户和AI助手的双方角色。在强化学习步骤中,人类训练者首先对模型先前创建的响应进行排名。这些排名被用于创建“奖励模型”,…
此外,OpenAI继续收集来自ChatGPT用户的数据,这些数据可以用于进一步训练和微调ChatGPT。用户可以赞或踩他们从ChatGPT收到的响应;在赞或踩时,他们还可以填写一个文本字段以提供额外的反馈。
更多细节可以参考:
维基百科ChatGPT: https://en.wikipedia.org/wiki/ChatGPT
InstructGPT论文: Training language models to follow instructions with human feedback

最后提一下,井字棋的最优策略竟是先占角!
https://www.guokr.com/article/4754

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/390332.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

扩展WSL2虚拟硬盘的大小

扩展WSL2虚拟硬盘的大小 1、在 Windows PowerShell 中终止所有 WSL 实例 wsl --shutdown2、查看 WSL 实例运行状态&#xff0c;确认关闭&#xff0c;并记住发行版的名称 wsl -l -v如果没有更改移动过发行版安装包位置&#xff0c;那么可以通过以下方法查找到发行版的安装包位…

[算法]选择排序

目录 1、选择排序的实现 2、例子 3、代码实现 4、时间复杂度和空间复杂度 5、选择排序的缺点——不稳定性 1、选择排序的实现 选择排序就是每一轮选择最小的元素直接交换到左侧。这种排序的最大优势&#xff0c;就是省去了多余的元素交换。 2、例子 原始数组和选择排序的…

NSIS 多语言安装界面

NSIS默认的打包界面多语言不太好用&#xff0c;因为界面不能跟着切换语言上面的文字也随着切换&#xff0c;所以只能是考虑自定义的方法解决这个问题 本人采用duilib与NSIS结合的方法&#xff0c;效果如下所示&#xff1a; ;获取系统默认的语言 System::Call Kernel32::Ge…

仪表放大器放大倍数分析-运算放大器

仪表放大器是一种非常特殊的精密差分电压放大器&#xff0c;它的主要特点是采用差分输入、具有很高的输入阻抗和共模抑制比&#xff0c;能够有效放大在共模电压干扰下的信号。本文简单分析一下三运放仪表放大器的放大倍数。 一、放大倍数理论分析 三运放仪表放大器的电路结构…

如何快速在企业网盘中找到想要的文件

现在越来越多的企业采用企业网盘来存储文档和资料&#xff0c;而且现在市面上的企业网盘各种各样。在使用企业网盘过程中&#xff0c;很多用户会问到企业网盘中如何快速搜索文件的问题。但是无论是“标签”功能还是普通的“关键词搜索”功能&#xff0c;都是单层级的&#xff0…

SAP MM学习笔记7-SAP标准功能和Add-on之间的关系

大家都知道SAP标准功能异常强大&#xff0c;而且也可以用ABAP做Add-on开发&#xff0c;在ERP市场长期占No1地位&#xff0c;那么SAP标准功能和Add-on之间到底有什么的关系呢&#xff1f; 咱们今天就来探讨一下。 1,一图说明标准和Add-on之间的关系 <图中上面一行> 1&am…

Javalin解构

Javalin Javalin是一个轻量级http框架&#xff0c;我们可以很容易的了解请求的处理过程及其设计&#xff0c;具有较高的学习意义。 从demo说起 public static void main(String[] args) {Javalin app Javalin.create(config -> {System.out.println("用户配置"…

Java——N叉树的层序遍历

题目链接 leetcode在线oj题——N叉树的层序遍历 题目描述 给定一个 N 叉树&#xff0c;返回其节点值的层序遍历。&#xff08;即从左到右&#xff0c;逐层遍历&#xff09;。 树的序列化输入是用层序遍历&#xff0c;每组子节点都由 null 值分隔&#xff08;参见示例&…

网络基础(三)

目录 网络层与数据链路层 ​编辑 网络层 IP协议 IP的构成 TCP和IP各自解决什么问题&#xff1f; 基本概念 协议头格式 协议头分析 如何分离与封装&#xff1f; 如何分用(向上交付)&#xff1f; 16位首部校验和 32位源IP和目的IP 4位版本 8位服务类型(Type Of…

【计算机】单位制前缀的歧义-KB、kb、MB混用

引言 经常遇到容量、带宽的单位&#xff0c;MB&#xff0c;GB在进行单位换算时&#xff0c;总是傻傻分不清&#xff0c;查些资料浅记录一下。 公制&#xff08;metric system&#xff09; 又译米制&#xff0c;是一个国际化十进位量度系统。法国在1799年开始使用公制&#xf…

【微信小程序】-- 页面导航 -- 声明式导航(二十二)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…

maven生命周期、阶段与默认绑定插件梳理

maven生命周期、阶段与默认绑定插件梳理 CSDN博客 码云源码 1.maven生命周期、阶段与默认绑定插件 序号生命周期lifecycle阶段phase默认绑定插件(链接官网)默认绑定插件(链接maven库)说明1cleancleanmaven-clean-pluginmaven-clean-plugin清理2.1buildvalidate——验证2.2b…

Unity记录1.1-入门-下载与创建项目

文章首发及后续更新&#xff1a;https://mwhls.top/4439.html&#xff0c;无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评&#xff0c;非常感谢&#xff01; 汇总&#xff1a;Unity 记录 写的很简略&#xff0c;因为不…

【数据挖掘与商务智能决策】第一章 数据分析与三重工具

numpy基础 numpy与数组 import numpy as np # 用np代替numpy,让代码更简洁 a [1, 2, 3, 4] # 创建列表a b np.array([1, 2, 3, 4]) #从列表ach print(a) print(b) print(type(a)) #打印a类型 print(type(b)) #打印b类型[1, 2, 3, 4] [1 2 3 4] <class ‘list’>…

目标检测: 数据增强代码详解

1. 常见的数据增强 1.1 翻转图像 左右水平翻转 假设图片的宽高为w,h,bdbox左上角A坐标为(x1,y1), 右下角B为(x2,y2)。经过左右水平翻转后,bdbox的左上角A1坐标(w-x2,y1) ,右下角B1坐标为(w-x1,y2)左右水平翻转的代码实现如下:from PIL import Image image = Image.open(i…

xmu 离散数学 卢杨班作业详解【4-7章】

文章目录第四章 二元关系和函数4.6.2911121618.120.222.1232834第五章 代数系统的一般概念2判断二元运算是否封闭348111214第六章 几个典型的代数系统1.5.6.7.11.12151618第七章 图的基本概念12479111215第四章 二元关系和函数 4. A{1,2,3} 恒等关系 IA{<1,1>,<2,2…

微服务到云原生

微服务到云原生 微服务 微服务架构&#xff08;Microservice Architecture&#xff09;是一种架构概念&#xff0c;旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 微服务是一种架构风格&#xff0c;一个大型复杂软件应用由一个或多个微服务组成。系统中的各…

为什么Gateway网关引入了LoadBalancer组件就拥有了负载均衡能力?

1、思考&#xff1a;一般而言&#xff0c;当我们在项目中引入了 LoadBalancer 负载均衡启动器组件&#xff0c;那么SpringBoot自动配置的ClassPath类路径加载机制会扫描到 LoadBalancer 类路径下的 spring.factories 配置文件&#xff0c;会注册一些Bean &#xff0c;但为什么网…

Java开发环境搭配

#Java开发环境搭建 oracle官网下载java https://www.oracle.com/cn/ 下载匹配电脑系统的版本 注意&#xff1a;安装路径不要包含中文 #JDK环境变量配置&#xff08;win10&#xff09; path 是一个常见的环境变量&#xff0c;它告诉系统除了在当前目录下寻找此程序外&#…

kafka3.0安装使用

一&#xff1a;定义 Kafka传 统定义&#xff1a;Kafka是一个分布式的基于发布/订阅模式的消息队列&#xff08;Message Queue&#xff09;&#xff0c;主要应用于大数据实时处理领域。 Kafka最 新定义 &#xff1a; Kafka是 一个开源的 分 布式事件流平台 &#xff08;Event St…