井字棋(三子棋)游戏的简单 C++ 实现与策略分析

井字棋作为一款简单而经典的游戏,一直深受大家喜爱。在这篇文章中,我将为大家分享我用 C++ 实现的井字棋代码,并对其进行详细介绍。

这里电脑会根据对局情况,判断下一步的位置。

一、头文件

我们使用 C++ 来构建这个游戏,主要依赖了以下几个头文件:

  • <iostream>:用于输入输出操作。
  • <string>:处理字符串相关的操作。
  • <windows.h>:在代码中用于实现一些特定的系统功能,比如控制控制台的显示。

二、整体代码结构

整个代码由多个函数组成,它们相互协作,共同实现了井字棋游戏的完整逻辑。

  • menu函数用于打印选择菜单
  • blankmap 函数负责将棋盘初始化为空白状态,为游戏的开始做好准备。
  • showmap 函数用于清晰地在控制台输出当前棋盘的状态,包括行列的标识和棋子的分布,让玩家能够直观地了解局面。
  • judge 函数是游戏胜负判定的核心,通过巧妙地计算棋子的 ASCII 码之和,来判断是玩家获胜、电脑获胜还是出现平局的情况。
  • player 函数处理玩家的回合,包括接收玩家输入的坐标,并进行合法性校验,然后在合法的位置放置玩家的棋子。
  • ai 函数则实现了电脑的下棋策略,电脑会先尝试寻找自己能够获胜的位置,如果没有,就检查是否能阻止玩家获胜,若都不行,则随机选择一个空位下棋。
  • playa 和 playb 分别是玩家先手和电脑先手的游戏循环控制函数,确保游戏按照规则有序进行。

三、关键函数解析

(一)blankmap 函数

这个函数通过简单的两层循环,将棋盘的每个位置初始化为空白,为游戏的开始做好准备。

void blankmap(char map[3][3]){
    for(int a=0;a<3;a++){
        for(int b=0;b<3;b++){
            map[a][b] = ' ';
        }
    }
}

(二)showmap 函数

它使用系统命令清屏,并以清晰直观的格式输出棋盘的当前状态,方便玩家查看。

void showmap(const char map[3][3]){
    system("cls");
    cout<<"    0 1 2 "<<endl; 
    cout<<"   -------"<<endl;
    for(int a=0;a<3;a++){ 
        cout<<a<<" | ";
        for(int b=0;b<3;b++){
            cout<<map[a][b]<<" ";
        }
        cout<<"|"<<endl;
    }
    cout<<"   -------"<<endl;
}

(三)judge 函数

judge函数是游戏胜负判定的核心。它通过巧妙计算棋子在行列和对角线上的 ASCII 码之和,准确判断出玩家获胜、电脑获胜或平局的情况。

string judge(const char map[3][3]){
    int a=0, b=0, c=0,d=0;

    // 判断行列
    for(int i=0;i<3;i++){
        a=map[i][0]+map[i][1]+map[i][2];
        b=map[0][i]+map[1][i]+map[2][i];
        if(a==126 || b==126){  // 比较 ASCII 码的和来判断输赢情况 
            return "玩家获胜!" ;
        }
        else if(a==192 || b==192){// 比较 ASCII 码的和来判断输赢情况 
            return "电脑获胜!"; 
        }
    }

    // 判断对角线 
    c=map[0][0]+map[1][1]+map[2][2];
    d=map[0][2]+map[1][1]+map[2][0];
    if(c==126 || d==126){
        return "玩家获胜!" ;
    }
    else if(c==192 || d==192){
        return "电脑获胜!"; 
    }

    // 判断是否下满棋盘
    else if(isfull(map)) {
        return "平局";
    }
    return "putin"; 
}

(四)player 函数

player函数负责处理玩家的输入,包括对输入的合法性检查和在合法位置放置玩家的棋子。

void player(char map[3][3]){
    if(isfull(map)){
        return;
    }
    // 玩家输入坐标
    int x=0, y=0;
    while(judge(map)=="putin"){
        cout <<"请输入横纵坐标: (中间加空格)"<<endl;
        cout <<"玩家棋子为'*', 电脑棋子为'@' :"<<endl; 
        cin >> y >> x; 

        // 判定输入是否有误并改变相应棋子 
        if(x<0 || x>2 ||y<0 || y>2){
            cout<<"输入有误!请重新输入!!!"<<endl;
            continue;
        }
        else if(map[x][y] == '*' || map[x][y]=='@'){
            cout<<"该位置已被棋子占用,请重新选择位置!"<<endl;
            continue;
        }
        else if(map[x][y]==' '){
            map[x][y]='*';
            break;
        }
    }
    showmap(map);
}

(五)ai 函数

ai函数实现了电脑的下棋策略。电脑首先尝试自己获胜,然后阻止玩家获胜,若都不行则随机选择空位下棋。

//电脑回合 
void ai(char map[3][3]) {
    // 如果棋盘已满,直接返回
    if (isfull(map)) {
        return;
    }
 	cout<<"电脑正在下棋,请稍后"<<endl;  //增加游戏体验,模拟电脑的思考    
	Sleep(1000);

    // 检查自己能否获胜
    // 检查行
    for (int i = 0; i < 3; i++) {  // 遍历每一行
        int countAt = 0, countEmpty = 0;  // 分别记录当前行中 '@' 的数量和空位置的数量
        for (int j = 0; j < 3; j++) {  // 遍历当前行的每一列
            if (map[i][j] == '@') {  // 如果位置为 '@'
                countAt++;  // 增加 '@' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '@' 的数量为 2 且空位置数量为 1
        if (countAt == 2 && countEmpty == 1) {
            for (int j = 0; j < 3; j++) {  // 再次遍历当前行
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查列
    for (int j = 0; j < 3; j++) {  // 遍历每一列
        int countAt = 0, countEmpty = 0;  // 分别记录当前列中 '@' 的数量和空位置的数量
        for (int i = 0; i < 3; i++) {  // 遍历当前列的每一行
            if (map[i][j] == '@') {  // 如果位置为 '@'
                countAt++;  // 增加 '@' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '@' 的数量为 2 且空位置数量为 1
        if (countAt == 2 && countEmpty == 1) {
            for (int i = 0; i < 3; i++) {  // 再次遍历当前列
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查对角线
    int countAtDiag1 = 0, countEmptyDiag1 = 0;  // 初始化主对角线 '@' 和空位置的计数
    int countAtDiag2 = 0, countEmptyDiag2 = 0;  // 初始化副对角线 '@' 和空位置的计数

    for (int i = 0; i < 3; i++) {  // 遍历对角线位置
        if (map[i][i] == '@') {  // 主对角线位置为 '@'
            countAtDiag1++;  // 增加主对角线 '@' 的计数
        } else if (map[i][i] ==' ') {  // 主对角线位置为空
            countEmptyDiag1++;  // 增加主对角线空位置的计数
        }

        if (map[i][2 - i] == '@') {  // 副对角线位置为 '@'
            countAtDiag2++;  // 增加副对角线 '@' 的计数
        } else if (map[i][2 - i] ==' ') {  // 副对角线位置为空
            countEmptyDiag2++;  // 增加副对角线空位置的计数
        }
    }

    // 主对角线如果 '@' 的数量为 2 且空位置数量为 1
    if (countAtDiag1 == 2 && countEmptyDiag1 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历主对角线
            if (map[i][i] ==' ') {  // 找到空位置
                map[i][i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 副对角线如果 '@' 的数量为 2 且空位置数量为 1
    if (countAtDiag2 == 2 && countEmptyDiag2 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历副对角线
            if (map[i][2 - i] ==' ') {  // 找到空位置
                map[i][2 - i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 检查能否阻止玩家获胜
    // 检查行
    for (int i = 0; i < 3; i++) {  // 遍历每一行
        int countStar = 0, countEmpty = 0;  // 分别记录当前行中 '*' 的数量和空位置的数量
        for (int j = 0; j < 3; j++) {  // 遍历当前行的每一列
            if (map[i][j] == '*') {  // 如果位置为 '*'
                countStar++;  // 增加 '*' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '*' 的数量为 2 且空位置数量为 1
        if (countStar == 2 && countEmpty == 1) {
            for (int j = 0; j < 3; j++) {  // 再次遍历当前行
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查列
    for (int j = 0; j < 3; j++) {  // 遍历每一列
        int countStar = 0, countEmpty = 0;  // 分别记录当前列中 '*' 的数量和空位置的数量
        for (int i = 0; i < 3; i++) {  // 遍历当前列的每一行
            if (map[i][j] == '*') {  // 如果位置为 '*'
                countStar++;  // 增加 '*' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '*' 的数量为 2 且空位置数量为 1
        if (countStar == 2 && countEmpty == 1) {
            for (int i = 0; i < 3; i++) {  // 再次遍历当前列
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查对角线
    int countStarDiag1 = 0;
	countEmptyDiag1 = 0;  // 初始化主对角线 '*' 和空位置的计数
    int countStarDiag2 = 0;
	countEmptyDiag2 = 0;  // 初始化副对角线 '*' 和空位置的计数

    for (int i = 0; i < 3; i++) {  // 遍历对角线位置
        if (map[i][i] == '*') {  // 主对角线位置为 '*'
            countStarDiag1++;  // 增加主对角线 '*' 的计数
        } else if (map[i][i] ==' ') {  // 主对角线位置为空
            countEmptyDiag1++;  // 增加主对角线空位置的计数
        }

        if (map[i][2 - i] == '*') {  // 副对角线位置为 '*'
            countStarDiag2++;  // 增加副对角线 '*' 的计数
        } else if (map[i][2 - i] ==' ') {  // 副对角线位置为空
            countEmptyDiag2++;  // 增加副对角线空位置的计数
        }
    }

    // 主对角线如果 '*' 的数量为 2 且空位置数量为 1
    if (countStarDiag1 == 2 && countEmptyDiag1 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历主对角线
            if (map[i][i] ==' ') {  // 找到空位置
                map[i][i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 副对角线如果 '*' 的数量为 2 且空位置数量为 1
    if (countStarDiag2 == 2 && countEmptyDiag2 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历副对角线
            if (map[i][2 - i] ==' ') {  // 找到空位置
                map[i][2 - i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 如果没有上述情况,随机选择
    int x = 0, y = 0;
    while (judge(map) == "putin") {  // 只要游戏未结束
        x = rand() % 3;  // 生成随机的 x 坐标
        y = rand() % 3;  // 生成随机的 y 坐标

        // 如果位置已被 '*' 或 '@' 占用
        if (map[x][y] == '*' || map[x][y] == '@') {
            continue;  // 重新生成坐标
        } else if (map[x][y] ==' ') {  // 如果位置为空
            map[x][y] = '@';  // 放置 '@'
            showmap(map);
            break;  // 完成操作并退出循环
        }
    }
    showmap(map);  // 显示当前棋盘状态
    return;
}

(六)playa 和 playb 函数

这两个函数分别控制玩家先手和电脑先手的游戏流程,通过循环交替玩家和电脑的回合,直到游戏结束。

void playa(char map[3][3]){
    showmap(map);
    do{
        player(map); 
        ai(map);
    }
    while(judge(map)=="putin");
    cout << judge(map) << endl;
}

void playb(char map[3][3]){
    showmap(map);
    do{
        ai(map);
        player(map); 
    }
    while(judge(map)=="putin");
    cout << judge(map) << endl;
}

四、游戏流程

当我们运行程序时,首先会看到一个菜单选项:

  1. 选择 1 开始游戏。
  2. 接着选择 a 表示玩家先手,选择 b 表示电脑先手,选择 c 退出游戏。

在游戏过程中,玩家和电脑轮流下棋,每一步都会更新并展示棋盘状态,直到游戏结束,判定出胜负或平局。

五、源代码

#include <iostream>
#include <string>
#include <windows.h>
using namespace std;

//将棋盘初始化为空白 
void blankmap(char map[3][3]);

//输出当前棋盘状态 
void showmap(const char map[3][3]);

//判定游戏结束与否 
string judge(const char map[3][3]);

//玩家回合
void player(char map[3][3]);

//电脑回合
void ai(char map[3][3]) ;

//游戏循环(玩家先手) 
void playa(char map[3][3]); 

//游戏循环(电脑先手) 
void playb( char map[3][3]); 

//判断棋盘是否有剩余空间
bool isfull(const char map[3][3]);
 
//菜单
void menu(); 

int main(){
	menu();
    system("pause");
	return 0;
} 

void menu(){
	char map[3][3];
	char choice;
	bool iscontinue=true;
    //界面选项 
	while(choice!='2'){
	cout<<"****************"<<endl;
	cout<<"* 1. 开始游戏  *"<<endl;
	cout<<"****************"<<endl;
    cout<<"* 2. 退出游戏  *"<<endl; 
    cout<<"****************"<<endl;
    cout<<"请输入1或2来选择: "<<endl; 
    
    cin>>choice;
    switch(choice){
       	case '1':
       		iscontinue=true;
       		while(iscontinue){
       		char s;
       		cout<<"****************"<<endl;
   	        cout<<"您可继续选择:"<<endl;
			cout<<" a. 玩家先手 "<<endl;
			cout<<" b. 电脑先手 "<<endl;
			cout<<" c. 退出游戏 "<<endl; 
			cin>>s;
			switch(s){
				case 'a':
			       blankmap(map);
	               playa(map);
	               continue;
	
	            case 'b':
	               blankmap(map);
	               playb(map);
	               continue;
	               
	            case 'c':
	            	iscontinue=false;
	            	break;
	            default:
	      	       	cout<<"输入错误,请重新输入!"<<endl;
	      	       	break;
			}
			   }

	    case '2':
	       cout<<"已退出游戏!";
	       choice='2';
	       break;
	    default:
            cout<<"输入错误,请重新输入!"<<endl;
            break;
		}
    } 
}
//初始化棋盘 
void blankmap(char map[3][3]){
	for(int a=0;a<3;a++){
		for(int b=0;b<3;b++){
			map[a][b] = ' ';
		}
	}
	
}

//打印棋盘 
void showmap(const char map[3][3]){
	system("cls");
	cout<<"    0 1 2 "<<endl; 
	cout<<"   -------"<<endl;
	for(int a=0;a<3;a++){ 
	 	cout<<a<<" | ";
	    for(int b=0;b<3;b++){
	  
			cout<<map[a][b]<<" ";
		}
		cout<<"|"<<endl;
	}
	
	cout<<"   -------"<<endl;
}


//判断游戏是否结束 
string judge(const char map[3][3]){
	int a=0, b=0, c=0,d=0;
	
   //判断行列	
	for(int i=0;i<3;i++){
		a=map[i][0]+map[i][1]+map[i][2];
		b=map[0][i]+map[1][i]+map[2][i];
		if(a==126 || b==126){  //比较ASCII码的和来判断输赢情况 
			return "玩家获胜!" ;
		}
		else if(a==192 || b==192){//比较ASCII码的和来判断输赢情况 
			return "电脑获胜!"; 
		}
	}

    //判断对角线 
	c=map[0][0]+map[1][1]+map[2][2];
	d=map[0][2]+map[1][1]+map[2][0];
	if(c==126 || d==126){
		return "玩家获胜!" ;
	}
	else if(c==192 || d==192){
		return "电脑获胜!"; 
	}
	
    //判断是否下满棋盘
    else if(isfull(map)) {
      return "平局";	
	}
	return "putin"; 

}

//判断棋盘是否满 
bool isfull(const char map[3][3]){
	for(int i=0;i<3;i++){
		for(int j=0;j<3;j++){
			if(map[i][j]==' '){
				return false;
			}
		}
	}
	return true;
}

//玩家回合 
void player(char map[3][3]){
	    if(isfull(map)){
	    	return;
		}
		 //玩家输入坐标
		int x=0, y=0;
		while(judge(map)=="putin"){
		cout <<"请输入横纵坐标: (中间加空格)"<<endl;
		cout <<"玩家棋子为'*' , 电脑棋子为'@' :"<<endl; 
		cin >> y >> x; 
		
		//判定输入是否有误并改变相应棋子 
		if(x<0 || x>2 ||y<0 || y>2){
			cout<<"输入有误!请重新输入!!!"<<endl;
			continue;
		}
		else if(map[x][y] == '*' || map[x][y]=='@'){
			cout<<"该位置已被棋子占用,请重新选择位置!"<<endl;
			continue;
			}
		else if(map[x][y]==' '){
			map[x][y]='*';
			break;
			}
		}
	showmap(map);
}

//电脑回合 
void ai(char map[3][3]) {
    // 如果棋盘已满,直接返回
    if (isfull(map)) {
        return;
    }
 	cout<<"电脑正在下棋,请稍后"<<endl;  //增加游戏体验,模拟电脑的思考    
	Sleep(1000);

    // 检查自己能否获胜
    // 检查行
    for (int i = 0; i < 3; i++) {  // 遍历每一行
        int countAt = 0, countEmpty = 0;  // 分别记录当前行中 '@' 的数量和空位置的数量
        for (int j = 0; j < 3; j++) {  // 遍历当前行的每一列
            if (map[i][j] == '@') {  // 如果位置为 '@'
                countAt++;  // 增加 '@' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '@' 的数量为 2 且空位置数量为 1
        if (countAt == 2 && countEmpty == 1) {
            for (int j = 0; j < 3; j++) {  // 再次遍历当前行
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查列
    for (int j = 0; j < 3; j++) {  // 遍历每一列
        int countAt = 0, countEmpty = 0;  // 分别记录当前列中 '@' 的数量和空位置的数量
        for (int i = 0; i < 3; i++) {  // 遍历当前列的每一行
            if (map[i][j] == '@') {  // 如果位置为 '@'
                countAt++;  // 增加 '@' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '@' 的数量为 2 且空位置数量为 1
        if (countAt == 2 && countEmpty == 1) {
            for (int i = 0; i < 3; i++) {  // 再次遍历当前列
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查对角线
    int countAtDiag1 = 0, countEmptyDiag1 = 0;  // 初始化主对角线 '@' 和空位置的计数
    int countAtDiag2 = 0, countEmptyDiag2 = 0;  // 初始化副对角线 '@' 和空位置的计数

    for (int i = 0; i < 3; i++) {  // 遍历对角线位置
        if (map[i][i] == '@') {  // 主对角线位置为 '@'
            countAtDiag1++;  // 增加主对角线 '@' 的计数
        } else if (map[i][i] ==' ') {  // 主对角线位置为空
            countEmptyDiag1++;  // 增加主对角线空位置的计数
        }

        if (map[i][2 - i] == '@') {  // 副对角线位置为 '@'
            countAtDiag2++;  // 增加副对角线 '@' 的计数
        } else if (map[i][2 - i] ==' ') {  // 副对角线位置为空
            countEmptyDiag2++;  // 增加副对角线空位置的计数
        }
    }

    // 主对角线如果 '@' 的数量为 2 且空位置数量为 1
    if (countAtDiag1 == 2 && countEmptyDiag1 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历主对角线
            if (map[i][i] ==' ') {  // 找到空位置
                map[i][i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 副对角线如果 '@' 的数量为 2 且空位置数量为 1
    if (countAtDiag2 == 2 && countEmptyDiag2 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历副对角线
            if (map[i][2 - i] ==' ') {  // 找到空位置
                map[i][2 - i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 检查能否阻止玩家获胜
    // 检查行
    for (int i = 0; i < 3; i++) {  // 遍历每一行
        int countStar = 0, countEmpty = 0;  // 分别记录当前行中 '*' 的数量和空位置的数量
        for (int j = 0; j < 3; j++) {  // 遍历当前行的每一列
            if (map[i][j] == '*') {  // 如果位置为 '*'
                countStar++;  // 增加 '*' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '*' 的数量为 2 且空位置数量为 1
        if (countStar == 2 && countEmpty == 1) {
            for (int j = 0; j < 3; j++) {  // 再次遍历当前行
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查列
    for (int j = 0; j < 3; j++) {  // 遍历每一列
        int countStar = 0, countEmpty = 0;  // 分别记录当前列中 '*' 的数量和空位置的数量
        for (int i = 0; i < 3; i++) {  // 遍历当前列的每一行
            if (map[i][j] == '*') {  // 如果位置为 '*'
                countStar++;  // 增加 '*' 的计数
            } else if (map[i][j] ==' ') {  // 如果位置为空
                countEmpty++;  // 增加空位置的计数
            }
        }
        // 如果 '*' 的数量为 2 且空位置数量为 1
        if (countStar == 2 && countEmpty == 1) {
            for (int i = 0; i < 3; i++) {  // 再次遍历当前列
                if (map[i][j] ==' ') {  // 找到空位置
                    map[i][j] = '@';  // 放置 '@'
                    showmap(map);
                    return;  // 完成操作并返回
                }
            }
        }
    }

    // 检查对角线
    int countStarDiag1 = 0;
	countEmptyDiag1 = 0;  // 初始化主对角线 '*' 和空位置的计数
    int countStarDiag2 = 0;
	countEmptyDiag2 = 0;  // 初始化副对角线 '*' 和空位置的计数

    for (int i = 0; i < 3; i++) {  // 遍历对角线位置
        if (map[i][i] == '*') {  // 主对角线位置为 '*'
            countStarDiag1++;  // 增加主对角线 '*' 的计数
        } else if (map[i][i] ==' ') {  // 主对角线位置为空
            countEmptyDiag1++;  // 增加主对角线空位置的计数
        }

        if (map[i][2 - i] == '*') {  // 副对角线位置为 '*'
            countStarDiag2++;  // 增加副对角线 '*' 的计数
        } else if (map[i][2 - i] ==' ') {  // 副对角线位置为空
            countEmptyDiag2++;  // 增加副对角线空位置的计数
        }
    }

    // 主对角线如果 '*' 的数量为 2 且空位置数量为 1
    if (countStarDiag1 == 2 && countEmptyDiag1 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历主对角线
            if (map[i][i] ==' ') {  // 找到空位置
                map[i][i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 副对角线如果 '*' 的数量为 2 且空位置数量为 1
    if (countStarDiag2 == 2 && countEmptyDiag2 == 1) {
        for (int i = 0; i < 3; i++) {  // 遍历副对角线
            if (map[i][2 - i] ==' ') {  // 找到空位置
                map[i][2 - i] = '@';  // 放置 '@'
                showmap(map);
                return;  // 完成操作并返回
            }
        }
    }

    // 如果没有上述情况,随机选择
    int x = 0, y = 0;
    while (judge(map) == "putin") {  // 只要游戏未结束
        x = rand() % 3;  // 生成随机的 x 坐标
        y = rand() % 3;  // 生成随机的 y 坐标

        // 如果位置已被 '*' 或 '@' 占用
        if (map[x][y] == '*' || map[x][y] == '@') {
            continue;  // 重新生成坐标
        } else if (map[x][y] ==' ') {  // 如果位置为空
            map[x][y] = '@';  // 放置 '@'
            showmap(map);
            break;  // 完成操作并退出循环
        }
    }
    showmap(map);  // 显示当前棋盘状态
    return;
}

//玩家先手情况 
void playa(char map[3][3]){
		showmap(map);
     	do{
     		player(map); 		 
     		ai(map);
		 }
		 while(judge(map)=="putin");
		 cout << judge(map) << endl;
}
//电脑先手情况 
void playb(char map[3][3]){
		showmap(map);
     	do{
     	    ai(map);	
		 	player(map); 
		 }
		 while(judge(map)=="putin");
		 cout << judge(map) << endl;
}

希望这篇博客能符合您的需求,代码可能有很多不足之处,希望大家能包容,给我一些宝贵的建议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值