嘘~ 正在从服务器偷取页面 . . .

三子棋模拟器 for linux


三子棋模拟器 for linux

中考前一周开摆写的

采用的是minimax算法和 \(\alpha - \beta\) 剪枝

目前是基于规则的估价函数(因为q779不会AI)

目前在含C++环境的 ubuntu20.04 和 macOS Monterey 12.4下都是可以编译的

代码:

//######
//
//      三子棋 for linux
//      Dev By q779
//      First Update 2021.6.6
//      Latest Update 2022.7.23
//      AI LEVEL  1.0
//
//######
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <random>
using namespace std;
#define int long long
#define INF (int)0x3f3f3f3f
#define maxDEP 5
struct Node
{
    int x=-1,y=-1,val=-INF;
};
//棋子:AI为1,玩家为2
int eval(int b[5][5],int k)
{
    int mark=k%2==0?2:1;//对手的
    int count=0;
    for(int i=1; i<=3; i++)
    {
        if((b[i][1]==mark||!b[i][1]) && (b[i][2]==mark||!b[i][2]) && (b[i][3]==mark||!b[i][3]))count++;
        if((b[1][i]==mark||!b[1][i]) && (b[2][i]==mark||!b[2][i]) && (b[3][i]==mark||!b[3][i]))count++;

        if(b[i][1]==1 && b[i][2]==1 && b[i][3]==1)return 50;
        if(b[1][i]==1 && b[2][i]==1 && b[3][i]==1)return 50;
        if(b[i][1]==2 && b[i][2]==2 && b[i][3]==2)return -50;
        if(b[1][i]==2 && b[2][i]==2 && b[3][i]==2)return -50;
    }

    if((b[1][1]==1 && b[2][2]==1 && b[3][3]==1) || (b[1][3]==1 && b[2][2]==1 && b[3][1]==1))return 50;
    if((b[1][1]==2 && b[2][2]==2 && b[3][3]==2) || (b[1][3]==2 && b[2][2]==2 && b[3][1]==2))return -50;

    if((b[1][1]==mark||b[1][1]==0) && (b[2][2]==mark||b[2][2]==0) && (b[3][3]==mark||b[3][3]==0))count++;
    if((b[1][3]==mark||b[1][3]==0) && (b[2][2]==mark||b[2][2]==0) && (b[3][1]==mark||b[3][1]==0))count++;

    return mark==1?count:-count;
}


//棋盘
struct board
{
    int body[5][5]={0};//棋盘
    int count=0;
    char AI='O',player='X';
    char kong=' ';

    //清空棋盘
    void clear(){memset(body,0,sizeof(body));}


    //输出棋盘
    void print()
    {
        puts("    1   2   3  ");
        for(int i=1; i<=3;i++)
        {
            puts("  -------------");
            printf("%c | ",char(i+48));
            for(int j=1; j<=3; j++)
            {
                if(body[i][j]==0)printf("  | ");
                if(body[i][j]==1)printf("%c | ",AI);
                if(body[i][j]==2)printf("%c | ",player);
                if(j==3)puts("");
            }
        }
        puts("  -------------");    
                
    }


    Node dfs(int k, int alpha, int beta)
    {
        if(k==maxDEP || count==9)
        {
            return Node({-1,-1,eval(body,k)});
        }
        int x=-1,y=-1;
        for(int i=1; i<=3; i++)
        for(int j=1; j<=3; j++)
            if(body[i][j]==0)
            {
                body[i][j]=k%2==0?1:2;
                count++;
                Node node=dfs(k+1,alpha,beta);
                if(k%2==0)//max
                {
                    if(node.val > alpha)
                    {
                        alpha=node.val;
                        x=i,y=j;
                    }
                    if(node.val >= beta)
                    {
                        body[i][j]=0;count--;
                        return Node({-1,-1,node.val});
                    }
                }else//min
                {
                    if(node.val < beta)
                    {
                        beta=node.val;
                        x=i,y=j;
                    }
                    if(node.val <= alpha)
                    {
                        body[i][j]=0;count--;
                        return Node({-1,-1,node.val});
                    }
                }
                body[i][j]=0;
                count--;
            }
        return Node({x,y,k%2==0?alpha:beta});
    }
    //循环游戏的主体
    void Loop()
    {
        print();
        bool flag=1;
        while(count<9)
        {
            

            int tx,ty;
            SCAN:;
            printf("input 坐标  列+[空格]+行 >");
            scanf("%lld%lld",&ty,&tx);
            if(tx<1||ty<1||tx>3||ty>3)
            {
                puts("非法输入!");
                goto SCAN;
            }
            if(body[tx][ty])
            {
                puts("那里已经有棋子了!");
                goto SCAN;
            }
            //放棋
            body[tx][ty]=2;count++;
            puts("");
            if(!flag)system("clear");flag=0;
            if(eval(body,0)>=50)
            {
                system("clear");
                puts("你被人工智能打败了!");
                puts("");
                print();
                return ;
            }else if(eval(body,0)<=-50)
            {
                system("clear");
                puts("你战胜了人工智能!");
                puts("");
                print();
                return;
            }else if(count==9)
            {
                system("clear");
                puts("平局,显然你打不过人工智能了!");
                puts("");
                print();
                return;
            }

            //AI下棋
            Node node = dfs(0,-INF,INF);
            if(body[node.x][node.y]==0)
            {
                body[node.x][node.y]=1;
                puts("");puts("");
                printf("AI 在 第%lld列 第%lld行 放了一颗棋子\n",node.y,node.x);
                puts("");puts("");system("clear");
                count++;
                if(eval(body,0)>=50)
                {
                    system("clear");
                    puts("你被人工智能打败了!");
                    puts("");
                    print();
                    return ;
                }
            }else
            {
                if(eval(body,0)<=-50)
                {
                    system("clear");
                    puts("你战胜了人工智能!");
                    puts("");
                    print();
                    return;
                }else
                {
                    system("clear");
                    puts("平局,显然你打不过人工智能了!");
                    puts("");
                    print();
                    return;
                }
            }
            print();
        }
    }
    
}main_body;

void start_game()
{
    int choose;
    printf("欢迎来到三子棋游戏!\n\n");
    printf("请选择你的棋子样式\n");
    puts("");
    puts("X  *********  [1]");
    puts("$  *********  [2]");
    puts("");

    printf("默认样式为 X\n");
    printf("> ");
    scanf("%lld",&choose);
    if(choose==1) main_body.player='X';
    if(choose==2) main_body.player='$';

    system("clear");
    printf("\n祝你好运\n\n\n\nPause any key to continue.\n");
    getchar();getchar();
    system("clear");

    main_body.Loop();
}

signed main()
{
    start_game();
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录