圈圈叉叉/井字棋/TicTacToe——C/C++实现

无聊,写个小游戏,井字棋

思路:

棋盘表达:二维数组打印

棋盘状态:数组元素标识:未下棋,下O和下X。

棋手:加计数器,奇偶判断区分两棋手。

胜利判断:横竖斜,一方能先连起来,这个直接拿出数据来比一下。还有棋盘下满等情况。

 

来来来,V1.0诞生了

 

#include<iostream>
using namespace std;

typedef enum TicTacToeState{
TTTS_Default = 0,
TTTS_O = 1,
TTTS_X = 2,
}TTTS;

void Print(TTTS array[][3])
{
	for(int i = 0;i < 3;i++)
	{
		for(int j = 0;j < 3;j++)
		{
			if(array[i][j] == TTTS_Default)
				cout << "-";		
			else if(array[i][j] == TTTS_O)
				cout << "O";
			else
				cout << "X";
		}
		cout << endl;
	}

}
TTTS CheckWin(TTTS array[][3])
{
	for(int i = 0;i < 3;i++)
		if(array[i][0] == array[i][1] && 
			array[i][0] == array[i][2] &&
			array[i][0] != TTTS_Default)
			return array[i][0];
	for(int j = 0;j < 3;j++)
		if(array[0][j] == array[1][j] &&
			array[0][j]== array[2][j] && 
			array[0][j] != TTTS_Default)
			return array[0][j];
	if(array[0][0] == array[1][1] &&
		array[0][0] == array[2][2] &&
		array[0][0] != TTTS_Default)
		return array[0][0];
	if(array[0][2] == array[1][1] &&
		array[0][2] == array[2][0] &&
		array[0][2] != TTTS_Default)
		return array[0][2];

	return TTTS_Default;
}

int main()
{
	TTTS array[3][3] = {TTTS_Default};
	int index_x,index_y;
	int counter = 0;

	Print(array);

	while(cin >> index_x >> index_y)
	{
		if(! ((index_x >= 0 && index_x < 3)&&(index_y >= 0 && index_y < 3))
			 || (array[index_x][index_y] != TTTS_Default))
		{
			cout << "wrong position,please retry!" << endl;
			continue;
		}
		//随便约定个先手
		array[index_x][index_y] = counter % 2 ? TTTS_O : TTTS_X; 

		//打印棋盘
		Print(array);
		//如果win,就break
		if(TTTS_O == CheckWin(array))
		{
			cout  << "game over,O win!!!!!" << endl;
			break;
		}else if(TTTS_X == CheckWin(array))
		{
			cout  << "game over,O win!!!!!" << endl;
			break;
		}
		
		counter++;//识别O和X
		if(counter >= 9 )//总步数达到9,或者加个或运算,可以判断全盘是否还有TTTS_Default,懒的写了
		{
			cout << "game over,draw game!" << endl;
			break;
		}
	}

}

 

 

 

 

 

 

 

 

 

 

 

可优化的部分

 

 

程序的OO化:

整体还是C的风格,用类封装一下,用一个对象表达一盘棋。可以用工厂模式同时开很多盘棋。

 


 

包裹一层循环,使得draw game可以直接开始下一盘

(不过如果打算OO化,就不用了,加上构造和析构,每次新开一个就好了)

 

 

 

 

必输和必胜情况的提前判定:

考虑:

OXX

OO-

X-X

此时,O怎么下都赢不了,X怎么下都赢,可以做成提前判定输赢(向后推演两棋手的棋招和结局,这不就是阿尔法狗干的事么,他不就是向后推N步,算输赢么,并且,还要更高级,并不是穷举所有结局,而是有优化过程,可惜我连最简单的还玩不转,不能窥其门径)

 

 

 

包裹一层循环,使得draw game可以直接开始下一盘

(不过如果打算OO化,就不用了,加上构造和析构,每次新开一个就好了)

 

友好度:

使用坐标,而非数组下标,不过这都没卵用了,简单。

还可以显示个轮到O或者轮到X下棋了。

 

可以考虑再弄个五子棋出来,感觉除了棋盘更大,主要的一点是计算胜利方法更麻烦了。

一个笨方法是遍历棋盘,每次碰到一个棋子,向右、向下、向右下三个方向判断,五个连续同色,胜利。

但是方法太蠢了,看看有没有其他方法,而且本例井字棋的方法也是挺蠢的,直接判断行、判断列、判断手动输入的斜线。本可以抽象化,不过它就三行,本来就简单,不想折腾了。

 

 

 

 

包裹一层循环,使得draw game可以直接开始下一盘

(不过如果打算OO化,就不用了,加上构造和析构,每次新开一个就好了)

 

 
  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!下面是一个简单的C++代码示例,实现井字棋游戏的基本功能: ```cpp #include <iostream> #include <vector> using namespace std; // 定义棋盘大小 const int SIZE = 3; // 定义棋盘格子状态 enum class CellState { Empty, X, O }; // 定义棋盘类 class TicTacToe { public: TicTacToe() { // 初始化棋盘 board.resize(SIZE, vector<CellState>(SIZE, CellState::Empty)); } // 显示棋盘 void displayBoard() { for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { switch (board[i][j]) { case CellState::Empty: cout << " "; break; case CellState::X: cout << "X"; break; case CellState::O: cout << "O"; break; } if (j != SIZE - 1) { cout << " | "; } } cout << endl; if (i != SIZE - 1) { cout << "---------" << endl; } } cout << endl; } // 下棋 bool makeMove(int row, int col, CellState player) { if (row < 0 || row >= SIZE || col < 0 || col >= SIZE || board[row][col] != CellState::Empty) { return false; } board[row][col] = player; return true; } // 判断游戏是否结束 bool isGameOver(CellState player) { // 判断行 for (int i = 0; i < SIZE; ++i) { bool win = true; for (int j = 0; j < SIZE; ++j) { if (board[i][j] != player) { win = false; break; } } if (win) { return true; } } // 判断列 for (int i = 0; i < SIZE; ++i) { bool win = true; for (int j = 0; j < SIZE; ++j) { if (board[j][i] != player) { win = false; break; } } if (win) { return true; } } // 判断对角线 bool win = true; for (int i = 0; i < SIZE; ++i) { if (board[i][i] != player) { win = false; break; } } if (win) { return true; } win = true; for (int i = 0; i < SIZE; ++i) { if (board[i][SIZE - i - 1] != player) { win = false; break; } } if (win) { return true; } return false; } private: vector<vector<CellState>> board; }; int main() { TicTacToe game; int row, col; CellState currentPlayer = CellState::X; while (true) { game.displayBoard(); cout << "Player " << (currentPlayer == CellState::X ? "X" : "O") << ", please enter your move (row col): "; cin >> row >> col; if (game.makeMove(row, col, currentPlayer)) { if (game.isGameOver(currentPlayer)) { cout << "Player " << (currentPlayer == CellState::X ? "X" : "O") << " wins!" << endl; break; } currentPlayer = (currentPlayer == CellState::X) ? CellState::O : CellState::X; } else { cout << "Invalid move. Please try again." << endl; } } return 0; } ``` 这段代码实现了一个基本的井字棋游戏,支持两位玩家轮流下棋,并判断游戏是否结束。希望对您有所帮助!如果您有任何问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值