首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++连接-四个小AI游戏(第二版)

C++连接-四个小AI游戏(第二版)
EN

Code Review用户
提问于 2021-07-20 06:11:25
回答 2查看 229关注 0票数 5

下面是改进的代码

代码语言:javascript
复制
#include 
#include 
#include 
#include 
#include 
#include 



enum class ending
{
    win ,
    lose ,
    tie
};
enum class States
{
    Human ,
    robot ,
    blank
};

enum class command
{
    deletE ,
    move
};


class BOARD {


public:
    std::vector Cells;
    BOARD(States type , int x , int y);
    bool wincon(const std::vector& rboard, int coordx, int coordy);
    

};

//functions
bool legal(const std::vector& Cells, int choice);
void printer(int x, int y, std::vector& Cells, char skin = 'K');
void instructions();
void newpage();
ending mainloop(int realx, int realy , char skin, std::vector& Cells, BOARD board);
void moving(int choice, std::vector& Cells, int cols, command decide , States player , int limit);
int Ai(std::vector& Cells, int coordx, int coordy , BOARD board );

int main()
{
    srand(static_cast(time(0)));
    //elements
    int realx, realy;
    char skin;
    //asking player for input and intro

    std::cout << "\t\t 4-CONNNECT \n\t________________________\n";
    std::cout << "enter x cordinate please:";
    std::cin >> realx;
    std::cout << "enter y cordinate please:";
    std::cin >> realy;
    BOARD board(States::Human, realx, realy);
    printer(realx, realy, board.Cells);
    instructions();
    std::cin.ignore(std::numeric_limits::max(), '\n');
    std::cin.get();
    newpage();
    //get player skin (letter) and pass it into game loop
    std::cout << "enter ur skin please:";
    std::cin >> skin;
    newpage();

    //test
    mainloop(realx, realy, skin, board.Cells, board);

}



//classes function defintion
BOARD::BOARD(States type , int x , int y)
{
    for (int i = 0; i < x; i++)
    {
        for (int j = 0; j < y; j++)
        {
            Cells.push_back(States::blank);
        }
    }
}

//function defintion
void printer(int x, int y, std::vector& Cells , char skin )
{
    int boardnumber = 0;
    for (int i = 0; i < x; i++)
    {
        for (int j = 0; j < y; j++)
        {
            switch (Cells[boardnumber])
            {
            case States::Human:
                std::cout << skin;
                std::cout << std::setw(2);
                break;
            case States::robot:
                std::cout << "B";
                std::cout << std::setw(2);
                break;
            case States::blank:
                std::cout << boardnumber+1;
                if (boardnumber+1 < 10) {
                    std::cout << std::setw(2);
                }
                break;
            default:
                break;
            }
            std::cout << "|";
            boardnumber++;
        }
        std::cout << "\n";
    }
}

void instructions()
{
    std::cout << "\ninstructions\n_________________\n";
    std::cout << "\n";
    std::cout << "just search google for instructions for this game :)\n";
}

void newpage()
{
    for (int i = 0; i < 50; i++)
    {
        std::cout << "\n";
    }
}


ending mainloop(int realx, int realy , char skin, std::vector& Cells, BOARD board)
{
    //elements
    int lobbyposition;
    int blank = 1;
    int limit = realx * realy;
    int userchoice , aichoice;

    //first or last
    std::cout << "start first(yes = 0 or no = 1):";
    std::cin >> lobbyposition;
    newpage();
    
    //loob

    while (blank != limit) {
        if (lobbyposition % 2 == 0) {
            printer(realx, realy, Cells, skin);
            std::cout << "enter the position:";
            std::cin >> userchoice;
            moving(userchoice , Cells, realy, command::move, States::Human , limit);
            newpage();
            printer(realx, realy, Cells, skin);
            std::cin.ignore(std::numeric_limits::max(), '\n');
            std::cin.get();
            newpage();
            blank++;
            lobbyposition++;
            if (board.wincon(Cells, realx, realy))
                return ending::win;
        }
        else if (lobbyposition % 2 != 0) {
            aichoice = Ai(Cells, realx, realy, board );
            printer(realx, realy, Cells, skin);
            std::cout << "\nmy result is :" << aichoice;
            newpage();
            printer(realx, realy, Cells, skin);
            std::cin.ignore(std::numeric_limits::max(), '\n');
            std::cin.get();
            newpage();
            blank++;
            lobbyposition++;
            if (board.wincon(Cells, realx, realy))
                return ending::lose;


        }

    }
    
}

bool BOARD::wincon(const std::vector& rboard, int coordx, int coordy)
{
    bool check = false;
    int equ1, equ2 , counter;
    counter = 0;
    States startvalue = rboard[counter];

        for (int x = 0; x < coordx; x++)
        {
            for (int y = 0; y < coordy; y++)
            {
                startvalue = rboard[counter];
                int possiblex[4][2] = { {0 , 1} , {1 , 0} , {1 , -1} , {1 , 1} };
                if (startvalue != States::blank) {
                //checkloop
                    for (int j = 0; j < 4; j++)
                    {
                        check = true;
                        int i = 0;
                        for (int b = 1; b < 4; ++b) {
                            equ1 = (x + (b * possiblex[j][i]));
                            equ2 = (y + (b * possiblex[j][i + 1]));
                            if (equ1 < 0 || equ1 == coordx) {
                                check = false;
                                break;
                            }
                            else if (equ2 < 0 || equ2 == coordy) {
                                check = false;
                                break;
                            }
                            else
                            {
                                if (rboard[equ2 + equ1 * coordy] != startvalue) {
                                    check = false;
                                }
                            }
                        }
                        if (check == true) {
                            return check;
                        }
                    }
                    

                }
                counter++;
            }
        }
    return check;
}

bool legal(const std::vector& Cells, int choice)
{
    int counter = 1;
    for (States loop : Cells){
        if (counter == choice)
        {
            if (loop != States::blank) {
                return false;
            }
            else {
                return true;
            }
        }
        counter++;
    }
    return false;
}
void moving(int choice, std::vector& Cells, int cols, command decide, States player , int limit)
{
    int position = choice+cols;
    while (legal(Cells, position) == true)
    {
        choice += cols;
        position += cols;
    }
    choice -= 1;
    if (decide == command::move) {
        Cells[choice] = player;
    }
    else if ( decide == command::deletE)
{
        if (legal(Cells, (choice+1)) != true){
            Cells[choice] = States::blank;
        }
        else {
            Cells[choice+cols] = States::blank;
        }
    }
}

int Ai(std::vector& Cells,int coordx, int coordy , BOARD board )
{
    //checkwin and stop win
    int limit = coordx * coordy;
    int counter = 1;
    while (counter < limit) {
        if (legal(Cells, counter)) {
            //check win
            moving(counter, Cells, coordy, command::move, States::robot, limit);
            if (board.wincon(Cells, coordx, coordy) == true) {
                return counter;
            }
            moving(counter, Cells, coordy, command::deletE, States::robot, limit);
        }
        counter++;
    }
    counter = 1;
    while (counter < limit) {
        if (legal(Cells, counter)) {
            //check enemy
            moving(counter, Cells, coordy, command::move, States::Human, limit);
            if (board.wincon(Cells, coordx, coordy) == true) {
                moving(counter, Cells, coordy, command::deletE, States::Human, limit);
                moving(counter, Cells, coordy, command::move, States::robot, limit);
                return counter;
            }
            moving(counter, Cells, coordy, command::deletE, States::Human, limit);
        }
        counter++;

    }
    //random number generatror (sry was lazy to updata to c++ 11, its too complicated for my brain)
    for (int i = 0; i < 1000; i++)
    {
        counter = (rand() % limit)+1;
        if (legal(Cells , counter)){
            moving(counter, Cells, coordy, command::move, States::robot , limit);
            return counter + 1;
        }
    }
}

这是我的第一个四通邮件的一个改进版本。我添加了类和枚举,我认为没有多维向量。

我还让代码看起来更好看,去掉了幼稚的名字。

EN

回答 2

Code Review用户

回答已采纳

发布于 2021-09-15 20:38:57

票数 5
EN

Code Review用户

发布于 2021-09-15 20:54:56

您的mainloopAi函数按值接受一个BOARD对象,这将生成一个副本。您可以将它们作为const BOARD &board传递以避免这种情况。而且,由于board对象已经拥有Cells数据,因此不需要将其作为单独的参数传入。

从你的评论接近尾声,你已经意识到你应该使用该语言提供的随机数工具。您包括了头,您应该使用它。对于这样一个简单的游戏来说,它不会有太大的区别,但是现在就抓住这个机会去学习它,这样你就会知道它的重要性。

坐标命名似乎是向后的,因为您使用y值进行水平索引,使用x进行垂直索引。这使得其他人更难理解,因为通常X是水平的,Y是垂直的。

BOARD构造函数正在做许多不必要的工作,而且它根本不使用type参数。你可以把它简化成

代码语言:javascript
复制
BOARD::BOARD(int x, int y): Cells(x * y, States::blank)
{
}

xy值应该存储在BOARD中,因为需要知道它们才能正确地访问Cells

printer可以是BOARD的成员,也可以是其他几个函数的成员(任何传递给Cells的函数都是很好的候选函数)。您的setw调用似乎位于错误的位置;它们应该位于要设置其宽度的值之前。boardnumber+1 < 10比较可以简化为boardnumber < 9,尽管如果您移动setws,您将需要比较boardnumber < 10。由于您不使用ij值,所以可以去掉它们。使用基于范围的for (for (auto c: Cells)),增加一个计数器来跟踪该列,并输出每个x列的换行符。

newpage可以使用静态char数组(手动填充换行符)或临时字符串(std::cout << std::string(50, '\n');),而不是一次输出一个换行符。考虑将该50更改为指定的常量。

mainloop不返回一个值,如果董事会填充(blank == limit),这是一个未定义的行为。你应该拿回一些东西,以表明这场比赛是平局。else if条件是不必要的,因为它将始终为true (因为如果lobbyposition % 2 == 0为false,则lobbyposition % 2 != 0为true)。

wincon中,根据需要声明变量,而不是函数开始。possiblex可以是static const int,以避免为每个位置构造数组。您似乎也在检查错误的位置(数组有向下、右、上、左、下和左)。您应该使用{ {0, 1}, {0, -1}, {1, 0}, {-1, 0} }。边界检查寻找下流,但不离开右侧或底部的网格。您需要在适当的位置使用equ1 >= coordxequ2 >= coordy检查它。如果break;检查将check设置为false,则可以添加D42

legal函数可以使用更好的名称。它做了很多工作,只是为了检查一个值。使用索引查找Cells中的值。为了简化这一点,添加一个索引函数来返回特定单元格的值,并在这里和wincon中使用它。

包括一些注释来解释其中一些函数所做的工作将有助于提高可读性。moving应该做什么?它看起来像是在选中的列中搜索标记,然后设置它。将legal改为xy值,并使用索引函数可以简化这一点,并避免从choice中添加或减去1。

Ai末尾的循环应该做什么?只有有限的几个动作可以做。如果它走得那么远,并且该循环运行到完成,那么您将不会从Ai返回任何可能在aichoice中返回一个字符串值的值。由于除了打印值之外,您没有做任何其他操作,所以没有什么真正的危害,但是如果这种使用发生变化,可能会发生一些不好的事情。(例如,如果将Ai逻辑分离到一个函数来决定移动,而另一个函数由Ai和进行移动的人工玩家共享,则可能会发生这种情况。)

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/264200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档