下面是改进的代码
#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;
}
}
}这是我的第一个四通邮件的一个改进版本。我添加了类和枚举,我认为没有多维向量。
我还让代码看起来更好看,去掉了幼稚的名字。
发布于 2021-09-15 20:38:57
发布于 2021-09-15 20:54:56
您的mainloop和Ai函数按值接受一个BOARD对象,这将生成一个副本。您可以将它们作为const BOARD &board传递以避免这种情况。而且,由于board对象已经拥有Cells数据,因此不需要将其作为单独的参数传入。
从你的评论接近尾声,你已经意识到你应该使用该语言提供的随机数工具。您包括了头,您应该使用它。对于这样一个简单的游戏来说,它不会有太大的区别,但是现在就抓住这个机会去学习它,这样你就会知道它的重要性。
坐标命名似乎是向后的,因为您使用y值进行水平索引,使用x进行垂直索引。这使得其他人更难理解,因为通常X是水平的,Y是垂直的。
BOARD构造函数正在做许多不必要的工作,而且它根本不使用type参数。你可以把它简化成
BOARD::BOARD(int x, int y): Cells(x * y, States::blank)
{
}x和y值应该存储在BOARD中,因为需要知道它们才能正确地访问Cells。
printer可以是BOARD的成员,也可以是其他几个函数的成员(任何传递给Cells的函数都是很好的候选函数)。您的setw调用似乎位于错误的位置;它们应该位于要设置其宽度的值之前。boardnumber+1 < 10比较可以简化为boardnumber < 9,尽管如果您移动setws,您将需要比较boardnumber < 10。由于您不使用i或j值,所以可以去掉它们。使用基于范围的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 >= coordx和equ2 >= coordy检查它。如果break;检查将check设置为false,则可以添加D42。
legal函数可以使用更好的名称。它做了很多工作,只是为了检查一个值。使用索引查找Cells中的值。为了简化这一点,添加一个索引函数来返回特定单元格的值,并在这里和wincon中使用它。
包括一些注释来解释其中一些函数所做的工作将有助于提高可读性。moving应该做什么?它看起来像是在选中的列中搜索标记,然后设置它。将legal改为x和y值,并使用索引函数可以简化这一点,并避免从choice中添加或减去1。
Ai末尾的循环应该做什么?只有有限的几个动作可以做。如果它走得那么远,并且该循环运行到完成,那么您将不会从Ai返回任何可能在aichoice中返回一个字符串值的值。由于除了打印值之外,您没有做任何其他操作,所以没有什么真正的危害,但是如果这种使用发生变化,可能会发生一些不好的事情。(例如,如果将Ai逻辑分离到一个函数来决定移动,而另一个函数由Ai和进行移动的人工玩家共享,则可能会发生这种情况。)
https://codereview.stackexchange.com/questions/264200
复制相似问题