当前位置: 首页 > news >正文

TicTacToe(井字棋 包含 3*3 和 4*4)游戏开发案例 【C++】

  • TicTacToe的成员函数

    • displayBoard(): 显示当前棋盘的状态。
    • makeMove(): 根据玩家输入的位置来更新棋盘。
    • checkWin(): 检查当前棋盘上是否有获胜的情况。
    • isBoardFull(): 检查棋盘是否已满,判断是否为平局。
    • changePlayer(): 切换当前玩家,从 'X' 到 'O' 或反之。
    • playGame(): 这是主循环,控制游戏的流程。
  • main()函数

    • 创建TicTacToe对象并调用playGame()函数来开始游戏。
#include <iostream>
#include <vector>

using namespace std;

class TicTacToe {
private:
    vector<vector<char>> board;  // 用来表示棋盘的二维数组
    char currentPlayer;          // 当前玩家('X' 或 'O')

public:
    // 构造函数:初始化棋盘和第一个玩家
    TicTacToe() {
        board = {{'1', '2', '3'},  // 初始化棋盘,位置用数字表示
                 {'4', '5', '6'},
                 {'7', '8', '9'}};
        currentPlayer = 'X';  // 初始玩家为 X
    }

    // 显示棋盘的函数
    void displayBoard() {
        cout << "玩家 X 和 玩家 O\n\n";
        // 打印棋盘的每一行
        cout << " " << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << " \n";
        cout << "---+---+---\n";
        cout << " " << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << " \n";
        cout << "---+---+---\n";
        cout << " " << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << " \n";
    }

    // 玩家进行移动,传入位置并判断是否合法
    bool makeMove(int position) {
        int row = (position - 1) / 3;  // 计算行号
        int col = (position - 1) % 3;  // 计算列号
        
        // 如果该位置没有被占用,则放置当前玩家的标记
        if (board[row][col] != 'X' && board[row][col] != 'O') {
            board[row][col] = currentPlayer;
            return true;  // 移动成功
        }
        return false;  // 如果该位置已经被占用,返回失败
    }

    // 检查是否有玩家获胜
    bool checkWin() {
        // 检查每一行和每一列是否相同
        for (int i = 0; i < 3; i++) {
            if ((board[i][0] == board[i][1] && board[i][1] == board[i][2]) ||
                (board[0][i] == board[1][i] && board[1][i] == board[2][i])) {
                return true;  // 如果某行或某列相同,表示获胜
            }
        }

        // 检查两个对角线
        if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) ||
            (board[0][2] == board[1][1] && board[1][1] == board[2][0])) {
            return true;  // 如果对角线相同,表示获胜
        }

        return false;  // 如果没有获胜,返回false
    }

    // 检查棋盘是否已满(平局)
    bool isBoardFull() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i][j] != 'X' && board[i][j] != 'O') {
                    return false;  // 如果有空格,则棋盘没有满
                }
            }
        }
        return true;  // 如果棋盘已满,返回true
    }

    // 切换玩家
    void changePlayer() {
        currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';  // 切换玩家:如果是X就变成O,反之亦然
    }

    // 运行游戏的主要逻辑
    void playGame() {
        int position;  // 玩家输入的位置
        bool validMove;  // 判断移动是否合法
        while (true) {
            displayBoard();  // 显示当前棋盘
            cout << "玩家 " << currentPlayer << " 的回合。请输入位置(1-9):";
            cin >> position;

            validMove = makeMove(position);  // 让玩家进行移动并检查是否合法
            if (!validMove) {
                cout << "无效的移动,请重试。\n";  // 如果移动无效,提示并继续
                continue;
            }

            if (checkWin()) {  // 检查是否有玩家获胜
                displayBoard();
                cout << "玩家 " << currentPlayer << " 获胜!\n";
                break;  // 游戏结束
            }

            if (isBoardFull()) {  // 检查棋盘是否已满(平局)
                displayBoard();
                cout << "游戏平局!\n";
                break;  // 游戏结束
            }

            changePlayer();  // 切换玩家
        }
    }
};

int main() {
    TicTacToe game;  // 创建一个TicTacToe对象,开始游戏
    game.playGame();  // 调用playGame函数开始游戏
    return 0;
}

  • 棋盘扩展

    • 采用了 4x4 的棋盘,棋盘初始化时标记为 '1''G',分别对应棋盘的 16 个位置。
  • 胜利条件

    • checkWin 函数被修改为检查是否有三子连珠。我们依旧检查每一行、每一列以及两条对角线中的任意三个连续的相同棋子。如果存在连续的三个相同棋子,则表示该玩家获胜。
    • 这里的 for 循环被调整为检查每行、每列中的连续三个位置是否相同。
  • 输入检查

    • 我们依然支持大小写输入(例如 Aa 都是有效输入),并且其他无效输入会提示重新输入。

#include <iostream>
#include <vector>
#include <cctype>  // 用于字符转换

using namespace std;

class TicTacToe {
private:
	vector<vector<char>> board;  // 用来表示棋盘的二维数组
	char currentPlayer;          // 当前玩家('X' 或 'O')

public:
	// 构造函数:初始化 4x4 棋盘和第一个玩家
	TicTacToe() {
		board = { {'1', '2', '3', '4'},
				 {'5', '6', '7', '8'},
				 {'9', 'A', 'B', 'C'},
				 {'D', 'E', 'F', 'G'} };
		currentPlayer = 'X';  // 初始玩家为 X
	}

	// 显示棋盘的函数
	void displayBoard() {
		cout << "玩家 X 和 玩家 O\n\n";
		// 打印棋盘的每一行
		for (int i = 0; i < 4; ++i) {
			for (int j = 0; j < 4; ++j) {
				cout << " " << board[i][j] << " ";
				if (j < 3) cout << "|";
			}
			cout << "\n";
			if (i < 3) cout << "---+---+---+---\n";
		}
	}

	// 将用户输入的位置(1-16 或 A-G 或 a-g)转换为对应的棋盘位置
	int convertPosition(char pos) {
		pos = toupper(pos);  // 将输入字符转换为大写字母,支持大小写
		if (isdigit(pos)) {
			return pos - '1';  // 如果是数字,转换为 0 到 15
		}
		else if (pos >= 'A' && pos <= 'G') {
			return pos - 'A' + 9;  // 如果是字母,转换为 9 到 15
		}
		return -1;  // 返回无效的位置
	}

	// 玩家进行移动,传入位置并判断是否合法
	bool makeMove(char position) {
		int index = convertPosition(position);  // 转换输入的字符为索引
		if (index == -1) return false;  // 如果输入无效,返回失败

		int row = index / 4;  // 计算行号
		int col = index % 4;  // 计算列号

		// 如果该位置没有被占用,则放置当前玩家的标记
		if (board[row][col] != 'X' && board[row][col] != 'O') {
			board[row][col] = currentPlayer;
			return true;  // 移动成功
		}
		return false;  // 如果该位置已经被占用,返回失败
	}

	// 检查是否有玩家获胜,依然是3子连珠的规则
	bool checkWin() {
		// 检查每一行和每一列是否相同(3子连珠)
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 2; j++) {  // 检查行
				if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && (board[i][j] == 'X' || board[i][j] == 'O')) {
					return true;
				}
			}

			for (int j = 0; j < 2; j++) {  // 检查列
				if (board[j][i] == board[j + 1][i] && board[j + 1][i] == board[j + 2][i] && (board[j][i] == 'X' || board[j][i] == 'O')) {
					return true;
				}
			}
		}

		// 检查对角线
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && (board[i][j] == 'X' || board[i][j] == 'O')) {
					return true;
				}
				if (board[i][3 - j] == board[i + 1][2 - j] && board[i + 1][2 - j] == board[i + 2][1 - j] && (board[i][3 - j] == 'X' || board[i][3 - j] == 'O')) {
					return true;
				}
			}
		}

		return false;  // 如果没有获胜,返回false
	}

	// 检查棋盘是否已满(平局)
	bool isBoardFull() {
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (board[i][j] != 'X' && board[i][j] != 'O') {
					return false;  // 如果有空格,则棋盘没有满
				}
			}
		}
		return true;  // 如果棋盘已满,返回true
	}

	// 切换玩家
	void changePlayer() {
		currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';  // 切换玩家:如果是X就变成O,反之亦然
	}

	// 运行游戏的主要逻辑
	void playGame() {
		char position;  // 玩家输入的位置
		bool validMove;  // 判断移动是否合法
		while (true) {
			displayBoard();  // 显示当前棋盘
			cout << "玩家 " << currentPlayer << " 的回合。请输入位置(1-9 或 A-G):";
			cin >> position;

			validMove = makeMove(position);  // 让玩家进行移动并检查是否合法
			if (!validMove) {
				cout << "无效的移动,请重试。\n";  // 如果移动无效,提示并继续
				continue;
			}

			if (checkWin()) {  // 检查是否有玩家获胜
				displayBoard();
				cout << "玩家 " << currentPlayer << " 获胜!\n";
				break;  // 游戏结束
			}

			if (isBoardFull()) {  // 检查棋盘是否已满(平局)
				displayBoard();
				cout << "游戏平局!\n";
				break;  // 游戏结束
			}

			changePlayer();  // 切换玩家
		}
	}
};

int main() {
	TicTacToe game;  // 创建一个TicTacToe对象,开始游戏
	game.playGame();  // 调用playGame函数开始游戏
	return 0;
}

相关文章:

  • 【数据结构】初识集合框架及背后的数据结构(简单了解)
  • Git和GitHub基础教学
  • 蓝耘携手通义万相2.1:引领AI创作革新,重塑视觉体验
  • python爬虫:Android自动化工具Auto.js的详细使用
  • 【Java学习】泛型
  • 知识库Dify和cherry无法解析影印pdf word解决方案
  • 个人记录,Unity资源解压和管理插件
  • FX-继承访问权限问题
  • 力扣经典题目:螺旋矩阵
  • 六十天前端强化训练之第十五天React组件基础案例:创建函数式组件展示用户信息(第15-21天:前端框架(React))
  • P2P中NAT穿越方案(UDP/TCP)(转)
  • [AI]从零开始的ComflyUI安装教程
  • Shell脚本编程基础篇(2)
  • 前端 UI 框架发展史
  • 基于javaweb的JSP+Servlet学生请假管理系统设计和实现(源码+文档+部署讲解)
  • git 贮藏
  • flink cdc同步mysql数据
  • 万字深度剖析——JS数据结构(上)
  • Redis7——进阶篇(五)
  • 微型计算机的结构
  • 连续两个交易日涨停,华夏幸福:生产经营活动正常,不存在影响股价波动的重大事宜
  • 技术派|台军首次试射“海马斯”火箭炮,如何压制这种武器?
  • 黄仁勋:新一代计算平台GB300三季度上市,AI计算能力每十年提升100万倍
  • 海南乐城管理局原局长贾宁已赴省政协工作,曾从河南跨省任职
  • “当代阿炳”甘柏林逝世,创办了国内第一所残疾人高等学府
  • 浙江广厦:诚挚道歉,涉事责任人交公安机关