Tic-Tac-Toe井字棋多模式C++实现

Tic-Tac-Toe井字棋多模式C++实现

根据网上的代码,利用C++实现了Tic-Tac-Toe井字棋的人机对弈、机人对弈、机机对弈、人人对弈。
关于 Tic-Tac-Toe的下法,可参考https://xkcd.com/832/给出的手绘图,如下:
https://xkcd.com/832/ Tic-Tac-Toe的最佳下棋位置

// https://xkcd.com/832/ 手绘X最佳下棋方式和O最佳下棋方式
/*  改编自:
https://blog.csdn.net/huqinweI987/article/details/52793048?utm_medium=distribute.pc_relevant_right.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant_right.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase
*/


#include<iostream>
using namespace std;

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

void Print(TTTS array[3][3]);   //打印提示及棋盘
TTTS CheckWin(TTTS array[][3]); //判断是否有胜者
int   FindOPos(TTTS net[][3]);  //寻找O棋子“最佳”部子位置
int   FindXPos(TTTS net[][3]);  //寻找X棋子“最佳”部子位置

int main()
{
    TTTS array[3][3] = { TTTS_Default };
    int index_x, index_y;
    int counter;
    int num[9];
    int iPlayer = 1;
    int iOpt = 0;

    Print(array);          //打印棋盘

    cout << "        X             O " << endl;
    cout << "0:   Player        Computer " << endl;   //人机对弈
    cout << "1:   Computer      Player " << endl;     //机人对弈
    cout << "2:   Computer      Computer " << endl;   //机机对弈
    cout << "3:   Player        Player " << endl;     //人人对弈
    cout << "Select a mode (0-3): " << endl;
    cin >> iPlayer;

   iOpt = FindXPos(array);    //iOpt 为棋盘上X棋最佳位置

   for(counter=0;counter<9;counter++) {

       if (counter % 2) {
           cout << "Play O input position(1-9) :" << endl;
       }
       else {
           cout << "Play X input position(1-9) :" << endl;
       }


       if(iPlayer != 3 ) {
       if (counter % 2== iPlayer)  //人机对弈 & 机人对弈
               while (cin >> num[counter])
           {
               index_x = (num[counter] - 1) / 3;
               index_y = (num[counter] - 1) % 3;
               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;
               }
               else
                   break;
           }
       else {     //   机机对弈 & 人机对弈 & 机人对弈
           num[counter] = iOpt;
           index_x = (num[counter] - 1) / 3;
           index_y = (num[counter] - 1) % 3;
       }
       }


       if( iPlayer == 3 ) {  //人人对弈
       while (cin >> num[counter])
       {
           index_x = (num[counter] - 1) / 3;
           index_y = (num[counter] - 1) % 3;
           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;
           }
           else
               break;
       }
       }


        array[index_x][index_y] = counter % 2 ? TTTS_O : TTTS_X;
       
        Print(array);  //打印棋盘
   
        if (counter % 2 == 0)   iOpt = FindOPos(array);    //找棋盘上最佳下一步棋的位置
        if (counter % 2 == 1)   iOpt = FindXPos(array);    //找棋盘上最佳下一步棋的位置

        if (counter<4) continue;
        if (CheckWin(array))      break;
       

        if (counter >= 8) cout <<"game over,draw game!" << endl;

   }
   cout << "\n本轮棋盘落子顺序:";

   for(int i = 0; i < counter; i++) { cout << num[i] <<"  ";  }
   cout <<"\n";

}



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

    if (ixo == TTTS_O)  cout << "game over,O win!!!!!" << endl;
    if (ixo == TTTS_X)  cout << "game over,X win!!!!!" << endl;

    return (TTTS)ixo;
}


//	打印棋盘 
void Print(TTTS array[3][3])
{
    system("cls");
    int i, j;

    printf("\n\t\t\tTic-Tac-Toe (井字棋或三连棋)\n");
    printf("\n\t规则:两人在九格方盘上分别轮流标记X和O, 先将三个同一记号排成横线、直线、斜线, 即是胜者\n");
    printf("\n\t棋盘位置编号\n");

    for (i = 0; i < 3; i++) {
        printf("\n\t+-+-+-+\n\t|");
        for (j = 0; j < 3; j++) {
            cout << i * 3 + j + 1 << "|";
        }
    }
    printf("\n\t+-+-+-+\n\n");


    printf("\n\n\t当前盘面\n");

    for (i = 0; i < 3; i++)
    {
        printf("\n\t+-+-+-+\n\t|");
        for (j = 0; j < 3; j++)
        {
            if (array[i][j] == TTTS_Default) printf(" ");
            if (array[i][j] == TTTS_O) printf("O");
            if (array[i][j] == TTTS_X) printf("X");
            printf("|");
        }
    }
    printf("\n\t+-+-+-+\n\n");

}


/* FindOPos 改自
https://blog.csdn.net/iteye_4389/article/details/82484665?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
*/
int   FindOPos(TTTS net[][3])
{

   // int net[3][3];//0 means null;1 means X;2 means O;
  
    int level[3][3] = { -1 };//越大优先级越高
    int o2 = 10000;//一个己方活二权值
    int x2 = 1000;//一个对方活二权值
    int x = 10;//一个对方活一权值
    int o = 6;//一个己方活一权值
    int nothing = 4;//一个空行权值

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (net[i][j] != 0) level[i][j] = 0;
            else {
                level[i][j] = 1;
                //横竖两条,每人都有
                //自己活二,,220
                if (((net[0][j] + net[1][j] + net[2][j]) == 4) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == -1)
                    level[i][j] = level[i][j] + o2;
                if (((net[i][0] + net[i][1] + net[i][2]) == 4) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == -1)
                    level[i][j] = level[i][j] + o2;

                //对方活二,110
                if (((net[0][j] + net[1][j] + net[2][j]) == 2) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 0)
                    level[i][j] = level[i][j] + x2;
                if (((net[i][0] + net[i][1] + net[i][2]) == 2) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 0)
                    level[i][j] = level[i][j] + x2;
                
                //单个X,100
                if (((net[0][j] + net[1][j] + net[2][j]) == 1) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 0)
                    level[i][j] = level[i][j] + x;
                if (((net[i][0] + net[i][1] + net[i][2]) == 1) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 0)
                    level[i][j] = level[i][j] + x;
                
                //单个O,200
                if (((net[0][j] + net[1][j] + net[2][j]) == 2) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 1)
                    level[i][j] = level[i][j] + o;
                if (((net[i][0] + net[i][1] + net[i][2]) == 2) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 1)
                    level[i][j] = level[i][j] + o;
                
                //空行,000
                if (((net[0][j] + net[1][j] + net[2][j]) == 0) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == -1)
                    level[i][j] = level[i][j] + nothing;
                if (((net[i][0] + net[i][1] + net[i][2]) == 0) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == -1)
                    level[i][j] = level[i][j] + nothing;

                //分情况
                //主对角线
                if ((i == 0 && j == 0) || (i == 2 && j == 2) || (i == 1 && j == 1)) {
                    //己方活二
                    if (((net[0][0] + net[1][1] + net[2][2]) == 4) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == -1)
                        level[i][j] = level[i][j] + o2;
                    //对方活二
                    if (((net[0][0] + net[1][1] + net[2][2]) == 2) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 0)
                        level[i][j] = level[i][j] + x2;
                    //单个X
                    if (((net[0][0] + net[1][1] + net[2][2]) == 1) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 0)
                        level[i][j] = level[i][j] + x;
                    //单个O
                    if (((net[0][0] + net[1][1] + net[2][2]) == 2) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 1)
                        level[i][j] = level[i][j] + o;
                    //空行,000
                    if (((net[0][0] + net[1][1] + net[2][2]) == 0) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == -1)
                        level[i][j] = level[i][j] + nothing;
                }

                //副对角线
                if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 1)) {
                    //己方活二
                    if (((net[0][2] + net[1][1] + net[2][0]) == 4) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == -1)
                        level[i][j] = level[i][j] + o2;
                    //对方活二
                    if (((net[0][2] + net[1][1] + net[2][0]) == 2) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 0)
                        level[i][j] = level[i][j] + x2;
                    //单个X
                    if (((net[0][2] + net[1][1] + net[2][0]) == 1) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 0)
                        level[i][j] = level[i][j] + x;
                    //单个O
                    if (((net[0][2] + net[1][1] + net[2][0]) == 2) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 1)
                        level[i][j] = level[i][j] + o;
                    //空行,000
                    if (((net[0][2] + net[1][1] + net[2][0]) == 0) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == -1)
                        level[i][j] = level[i][j] + nothing;
                }//the end of for if
            }//the end of if
        }//the end of for j
    }//the end of for j


    //寻找最大权值的位置
    int maxi = 0, maxj = 0, temp = -1;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (level[i][j] > temp)
            {

                temp = level[i][j];
                maxi = i;
                maxj = j;
            }
            //System.out.println("net[i][j]=" + net[i][j]);
            //System.out.println("level[i][j]=" + level[i][j]);

        }
    }
    cout <<"建议下棋位置: "<< maxi * 3 + maxj + 1 << "  推荐度为:" << temp << '\n';

    return maxi * 3 + maxj + 1;


}


int   FindXPos(TTTS net1[][3])
{
    // 交换X和O的位置,判断X的最佳位置
    TTTS net[3][3] = { TTTS_Default };//0 means null;1 means O;2 means X;

    int level[3][3] = { -1 };//越大优先级越高
    int o2 = 10000;//一个己方活二权值
    int x2 = 1000;//一个对方活二权值
    int x = 10;//一个对方活一权值
    int o = 6;//一个己方活一权值
    int nothing = 4;//一个空行权值


    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (net1[i][j] == TTTS_O)   net[i][j] = TTTS_X;
            if (net1[i][j] == TTTS_X)   net[i][j] = TTTS_O;
        }
    }


    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (net[i][j] != 0) level[i][j] = 0;
            else {
                level[i][j] = 1;
                //横竖两条,每人都有
                //自己活二,,220
                if (((net[0][j] + net[1][j] + net[2][j]) == 4) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == -1)
                    level[i][j] = level[i][j] + o2;
                if (((net[i][0] + net[i][1] + net[i][2]) == 4) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == -1)
                    level[i][j] = level[i][j] + o2;

                //对方活二,110
                if (((net[0][j] + net[1][j] + net[2][j]) == 2) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 0)
                    level[i][j] = level[i][j] + x2;
                if (((net[i][0] + net[i][1] + net[i][2]) == 2) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 0)
                    level[i][j] = level[i][j] + x2;

                //单个X,100
                if (((net[0][j] + net[1][j] + net[2][j]) == 1) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 0)
                    level[i][j] = level[i][j] + x;
                if (((net[i][0] + net[i][1] + net[i][2]) == 1) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 0)
                    level[i][j] = level[i][j] + x;

                //单个O,200
                if (((net[0][j] + net[1][j] + net[2][j]) == 2) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == 1)
                    level[i][j] = level[i][j] + o;
                if (((net[i][0] + net[i][1] + net[i][2]) == 2) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == 1)
                    level[i][j] = level[i][j] + o;

                //空行,000
                if (((net[0][j] + net[1][j] + net[2][j]) == 0) && (net[0][j] * net[1][j] * net[2][j]) == 0 && ((net[0][j] - 1) * (net[1][j] - 1) * (net[2][j] - 1)) == -1)
                    level[i][j] = level[i][j] + nothing;
                if (((net[i][0] + net[i][1] + net[i][2]) == 0) && (net[i][0] * net[i][1] * net[i][2]) == 0 && ((net[i][0] - 1) * (net[i][1] - 1) * (net[i][2] - 1)) == -1)
                    level[i][j] = level[i][j] + nothing;

                //分情况
                //主对角线
                if ((i == 0 && j == 0) || (i == 2 && j == 2) || (i == 1 && j == 1)) {
                    //己方活二
                    if (((net[0][0] + net[1][1] + net[2][2]) == 4) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == -1)
                        level[i][j] = level[i][j] + o2;
                    //对方活二
                    if (((net[0][0] + net[1][1] + net[2][2]) == 2) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 0)
                        level[i][j] = level[i][j] + x2;
                    //单个X
                    if (((net[0][0] + net[1][1] + net[2][2]) == 1) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 0)
                        level[i][j] = level[i][j] + x;
                    //单个O
                    if (((net[0][0] + net[1][1] + net[2][2]) == 2) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == 1)
                        level[i][j] = level[i][j] + o;
                    //空行,000
                    if (((net[0][0] + net[1][1] + net[2][2]) == 0) && (net[0][0] * net[1][1] * net[2][2]) == 0 &&
                        ((net[0][0] - 1) * (net[1][1] - 1) * (net[2][2] - 1)) == -1)
                        level[i][j] = level[i][j] + nothing;
                }

                //副对角线
                if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 1)) {
                    //己方活二
                    if (((net[0][2] + net[1][1] + net[2][0]) == 4) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == -1)
                        level[i][j] = level[i][j] + o2;
                    //对方活二
                    if (((net[0][2] + net[1][1] + net[2][0]) == 2) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 0)
                        level[i][j] = level[i][j] + x2;
                    //单个X
                    if (((net[0][2] + net[1][1] + net[2][0]) == 1) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 0)
                        level[i][j] = level[i][j] + x;
                    //单个O
                    if (((net[0][2] + net[1][1] + net[2][0]) == 2) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == 1)
                        level[i][j] = level[i][j] + o;
                    //空行,000
                    if (((net[0][2] + net[1][1] + net[2][0]) == 0) && (net[0][2] * net[1][1] * net[2][0]) == 0 &&
                        ((net[0][2] - 1) * (net[1][1] - 1) * (net[2][0] - 1)) == -1)
                        level[i][j] = level[i][j] + nothing;
                }//the end of for if
            }//the end of if
        }//the end of for j
    }//the end of for j


    //寻找最大权值的位置
    int maxi = 0, maxj = 0, temp = -1;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (level[i][j] > temp)
            {

                temp = level[i][j];
                maxi = i;
                maxj = j;
            }
            //System.out.println("net[i][j]=" + net[i][j]);
            //System.out.println("level[i][j]=" + level[i][j]);

        }
    }
    cout << "建议下棋位置: " << maxi * 3 + maxj + 1 << "  推荐度为:" << temp << '\n';

    return maxi * 3 + maxj + 1;


}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值