C++迭代 2D 向量以查找连续 3 个向量

发布于 2024-09-30 20:50:48 字数 786 浏览 5 评论 0原文

大家好,正在开发一个 C++ 小游戏“Connect 3”。这就像 连接 4,但我们只需要匹配 3 即可赢得比赛。我将我的板存储在一个包含整数的二维向量中。

vector< vector<int> > vector2d;

我有一个“X”存储为 1,一个“O”存储为 -1,其中 0 是一个空格。到目前为止似乎正在发挥作用。

因此,在我与计算机对战的算法中,它会找到可能的最佳走法。我已经完成了算法,但它需要知道何时达到“基本情况”。 (它是递归的。)基本情况是:

  1. 有人连续获得 3 个,或者
  2. 棋盘已满

检查棋盘是否已满很容易。我只是迭代并查看是否有空格为“0”。如果是,则董事会未满。但在我检查之前,我需要看看是否有人连续获得 3 个,这就是我遇到的问题。我能想到的唯一方法是大而复杂,遍历棋盘 3 次不同的时间,寻找 3 的水平匹配、3 的垂直匹配和 3 的对角匹配。我什至不知道从哪里开始这样做,我希望有更好的方法来做到这一点。非常感谢您的帮助!

另外,不确定我是否可以使用 Boost,到目前为止我还没有,而且我不想使用它。 (不确定学校电脑是否有)。

编辑: 棋盘不需要是 3 x 3。它可以是 1 x 7、7 x 7 或任何尺寸。如果它不是合法大小 (0,0),我的代码会告诉用户,但任何其他板都应该可以工作。我使用矢量大小来查看棋盘有多大。

Hey all, working on a C++ little game, "Connect 3." This is just like Connect 4, except we only need a match of 3 to win the game. I am storing my board in a 2D vector, which holds ints.

vector< vector<int> > vector2d;

And I have an "X" stored as a 1, and an "O" stored as a -1, with 0 being an empty space. It seems to be working so far.

So, in my algorithm for playing against the computer, it finds the best move possible. I have the algorithm finished, but it needs to know when a "base case" has been hit. (It's recursive.) A base case is either:

  1. Someone has gotten 3 in a row, or
  2. The board is full

Checking if the board is full is easy. I just iterate through and see if any space is a "0". If it is, the board isn't full. But before I check that, I need to see if anyone has gotten 3 in a row, which is where I'm having issues. The only way I can think of doing this is big and complicated, going through the board 3 different times, looking for Horizontal matches of 3, vertical matches of 3, and Diagonal matches of 3. I'm not even sure where to begin in doing that, and I'm hoping there is a better way to do this. Help would be much appreciated!

Also, not sure I'm allowed to use Boost, I haven't yet so far, and I'd like to not have to use it. (Not sure if the school computers have it).

Edit: The board does not need to be 3 by 3. It could be 1 by 7, 7 by 7, or any size. If it's not a legal size (0,0), my code will tell the user that, but any other board should work. I've used the vector sizes to see how big the board is.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

执妄 2024-10-07 20:50:48

您不必每次都检查整个板。只有新的部分才会产生影响,因此您只需检查包含新部分的最终条件。您需要检查 8 个不同的方向,但每两个方向都在同一条线上,应一起检查。方向可以定义为 (delta_X, delta_Y) 对:(1,0),(0,1),(1,1),(1,-1)。您的代码应该在每个方向上遍历(如 Leonid 的代码),并尝试计算与新块具有相同值的尽可能多的块。然后它应该从当前方向沿相反的方向(-x,-y)遍历,并计算这些碎片。如果计数的件数为 N-1(新件已计数),则您获胜。

You don't have to check the whole board every time. Only the new piece makes a difference so you only have to check those end conditions that include the new piece. There are 8 different directions you need to check, but every two of them are on the same line and should be checked together. Directions can be defined as (delta_X, delta_Y) pairs: (1,0),(0,1),(1,1),(1,-1). Your code should traverse in each direction (as in code from Leonid) and try to count as many pieces with the same value as new piece. Then it should traverse in opposite direction which is (-x,-y) from current direction, and count those pieces as well. If the number of counted pieces is N-1 (new piece is already counted) then you have a winner.

橘虞初梦 2024-10-07 20:50:48

假设您使用的是 3x3 板。可以形成的获胜线的数量是有限的。

1 0 0    1 1 1   1 0 0   0 0 1   0 0 1   0 0 0   0 0 0   0 1 0
1 0 0    0 0 0   0 1 0   0 1 0   0 0 1   1 1 1   0 0 0   0 1 0
1 0 0    0 0 0   0 0 1   1 0 0   0 0 1   0 0 0   1 1 1   0 1 0

现在,如果您给每个棋盘位置一个位分配,如下所示:

 1   2   4
 8  16  32
64 128 256

现在您可以计算出 8 条获胜线如下:

  1 |   8 |  64  = 73
  1 |   2 |   4  = 7
  1 |  16 | 256  = 273
  4 |  16 |  64  = 84
  4 |  32 | 256  = 292
  8 |  16 |  32  = 56
 64 | 128 | 256  = 448
  2 |  16 | 128  = 146

现在,如果您在给定玩家拥有的任何位位置存储 1,您可以轻松地单步执行每个上面的“解决方案”并针对上面的 8 个值进行测试。

因此,假设 2 名玩家有以下位置:

  1 1 0  0 0 1
  1 0 0  0 1 1
  1 0 1  0 1 0

如果将“解决方案”中的值加起来,如下所示

  1 |  2 |  8 |  64 | 256 = 331
  4 | 16 | 32 | 128       = 180

,我们知道获胜线是 1 | 。 8 | 64 = 73 行,因此我们可以使用位明智进行测试,如下所示

  331 & 73 = 73
  180 & 73 = 0

因此我们可以轻松检测到玩家 1 连续有 3 个,并且由于“and”的结果不为 0,因此有 1 个。

这意味着您可以计算出获胜者最多 8 个步骤(即根据 8 个可能的答案检查两个玩家的跑动总数)。

显然,随着你变得更大,复杂性也会增加,当你用完位时,它看起来会变得更加复杂(看看 std::bitset,例如如何处理它),但最终游戏总是需要比蛮力法。显然,设置需要更多的时间,但您只需计算每种棋盘类型一次的最终游戏条件,以便时间在多次游戏中摊销。

无论如何......我就是这么做的:D

So lets say you are using an 3x3 board. There are a finite number of winning lines that can be formed.

1 0 0    1 1 1   1 0 0   0 0 1   0 0 1   0 0 0   0 0 0   0 1 0
1 0 0    0 0 0   0 1 0   0 1 0   0 0 1   1 1 1   0 0 0   0 1 0
1 0 0    0 0 0   0 0 1   1 0 0   0 0 1   0 0 0   1 1 1   0 1 0

Now if you give each board location a bit assignment as follows:

 1   2   4
 8  16  32
64 128 256

now you can work out that the 8 winning lines are as follows:

  1 |   8 |  64  = 73
  1 |   2 |   4  = 7
  1 |  16 | 256  = 273
  4 |  16 |  64  = 84
  4 |  32 | 256  = 292
  8 |  16 |  32  = 56
 64 | 128 | 256  = 448
  2 |  16 | 128  = 146

Now if you store a 1 in any bit position that a given player has you can easily step through each of the "solutions" above and test against the 8 values above.

So suppose the 2 players have the following positions:

  1 1 0  0 0 1
  1 0 0  0 1 1
  1 0 1  0 1 0

If you tot up there values as done for the "solutions" as follows you get

  1 |  2 |  8 |  64 | 256 = 331
  4 | 16 | 32 | 128       = 180

So we know the winnign line is the 1 | 8 | 64 = 73 line so we can test using a bit wise and as follows

  331 & 73 = 73
  180 & 73 = 0

So we can easily detect that player 1 has 3 in a row and has one as the result of the "and" is not 0.

This means you can calculate a winner in a maximum of 8 steps (ie checking both players running totals against the 8 possible answers).

Obviously complexity increases as you get larger and it can seem a lot more complicated when you run out of bits (look at std::bitset, for example of how to handle that) but the end game will ALWAYS take less iterations to check than a brute force method. Obviously it takes a bit more time to set up but you only calculate the end game conditions once per board type so that time gets amortised across several plays.

Anyway ... Thats how I'd do it :D

衣神在巴黎 2024-10-07 20:50:48

从算法复杂度的角度来看,以下 C++ O(N*M) 解决方案是最好的解决方案,因为我们需要在最坏的情况下检查电路板的每个单元。它迭代棋盘中的所有单元格(ij),尝试朝 4 个方向前进(k),并从那里检查k 方向上的 3 个单元格 (l) 被占用且相等。

vector<vector<int> > board(n, vector<int>(m)); // initialize
/*          down  down-right right  up-right */
int di[] = {1,    1,          0,    -1        }; // four directions i coordinate
int dj[] = {0,    1,          1,     1        }; // four directions j coordinate
for (int i = 0; i < n; i++) { // for each row
    for (int j = 0; j < m; j++) { // for each column
        for (int k = 0; k < 4; k++) { // for each direction
            int ii = i, jj = j;
            bool found = true;
            if (board[ii][jj] == 0) continue; // empty space
            for (int l = 1; l < 3 && found; l++) { // need 3 in a row
                int iii = ii + di[k], jjj = jj + dj[k];
                if (iii < 0 || iii >= n) found = false, continue; // off bounds
                if (jjj < 0 || jjj >= n) found = false, continue; // off bounds
                if (board[iii][jjj] != board[ii][jj]) found = false;
            }
            if (found) {
                printf("Hurray!\n");
                return;
            }
        }
    }
}

The following C++ O(N*M) solution from algorithmical complexity perspective is the best possible as we need to check in the worst case each cell of the board. It iterates over all cells in the board (i and j), tries to go in 4 directions (k), and from there checks that 3 cells (l) in direction k are occupied and equal.

vector<vector<int> > board(n, vector<int>(m)); // initialize
/*          down  down-right right  up-right */
int di[] = {1,    1,          0,    -1        }; // four directions i coordinate
int dj[] = {0,    1,          1,     1        }; // four directions j coordinate
for (int i = 0; i < n; i++) { // for each row
    for (int j = 0; j < m; j++) { // for each column
        for (int k = 0; k < 4; k++) { // for each direction
            int ii = i, jj = j;
            bool found = true;
            if (board[ii][jj] == 0) continue; // empty space
            for (int l = 1; l < 3 && found; l++) { // need 3 in a row
                int iii = ii + di[k], jjj = jj + dj[k];
                if (iii < 0 || iii >= n) found = false, continue; // off bounds
                if (jjj < 0 || jjj >= n) found = false, continue; // off bounds
                if (board[iii][jjj] != board[ii][jj]) found = false;
            }
            if (found) {
                printf("Hurray!\n");
                return;
            }
        }
    }
}
日暮斜阳 2024-10-07 20:50:48

我制作了一个这样的游戏,实际上是我用 C++ 制作的第一个游戏(谁需要 hello world :P)

,每个人都可以使用它,如果他们愿意的话。

只是不要忘记这是我的第一个 C++ 东西,而且它的编码绝对不正确:P,但它有一些不错的 C++ 东西,比如其中的东西。但其中有一个 100% 优化的搜索算法,它检查所需排列的绝对最少数量,以检查连续三个获胜条件,并带有大量注释和 ASCII 艺术。这可能非常有用。

哦差点忘了提一下,这是一个控制台应用程序(黑屏 DOS 环境,无论它叫什么)。它有一个人工智能(如果这是我的最新版本)应该做得很好。而且网格是动态构建的(这是最困难的部分)你可以连续玩 3 个,但最大网格为 20x20(我发现这个游戏很蹩脚,在重力作用下连续 4 个更有趣)

在这里你开始:

// DrieOpEenRij.cpp : Defines the entry point for the console application.

     #include "stdafx.h"
     #include <iostream>
     #include <string>
     #include <typeinfo>

    using namespace std;

    typedef unsigned short USHORT;

    //USE ONLY IN A SQUARE GRID
    //This method checks a win for the minimimum amount of spaces covering 100% amount of the grid
    //It has 100% coverage and close to 0% overhead, discrimination between who to check for is required and
    //so currentMove char is required to check for win on 'H' human and 'C' Computer
    void CheckForWin(const char* Grid_ptr , const USHORT GridSize , const USHORT GridWidth ,bool &humanWin, bool &computerWin, const char currentMove)
    {
        //check for an x from 1-end of array
        //for all x's check if that makes a 3 line once per linetype
        //check for horizontal win (dont get overhead on edges)

    //A non square grid will have been detected by now
    const USHORT rowStart = 0;
    const USHORT rowEnd = GridWidth-1;
    USHORT passRowCounter = 1;
    const USHORT Side = GridWidth;

    const USHORT cond1 = rowEnd-2;
    const USHORT cond2 = GridSize-Side*2;   

    //Check for all human win options ( after a human move )
    if (currentMove == 'H')
    {
        //Check for human win code
        //Check all array slots for an occurence of 'X'
        for(USHORT i = 0; i < GridSize; i++)
        {   
            //Local stack variables, optimizations for iterations in loops and if statements,
            //also for readability, this is (only efficient and) done only when it is guaranteed
            //to be used in every for jump. 
            USHORT iModSide = i % Side;
            USHORT SideMinTwo = Side - 2;
            USHORT SidePlusTwo = Side + 2;
            USHORT iPlusSide = i + Side;
            USHORT iPlusSideTimesTwo = i + Side * 2;
            USHORT iPlusOne = i + 1;
            USHORT iPlusTwo = i + 2;

            //If an X is found evaluate a win scenario
            if (Grid_ptr[i] == 'X')
            {
                //For each row -->
                if (iModSide < SideMinTwo)
                {
                    //Check horizontal win from left to right
                    if (Grid_ptr[i + 1] == 'X' && Grid_ptr[i + 2] == 'X')
                    {
                        humanWin = true;
                        break;
                    }
                }

                //For the two values under the 'X' (colomn wise) check for 'X''X'
                if (iPlusSideTimesTwo < GridSize)
                {
                    if(Grid_ptr[iPlusSide] == 'X' && Grid_ptr[iPlusSideTimesTwo] == 'X')
                    {
                        humanWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [X] [X] [?] [?]   This illustration shows that checking only at X will suffice
                // [X] [X] [?] [?]   for this specific check in screening for all Top Left --> Down Right
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Right --> Down Left is done mirrored
                // [?] [?] [?] [?]   All other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (iPlusSideTimesTwo < GridSize && iModSide < SideMinTwo)
                {
                    if (Grid_ptr[i+Side+1] == 'X' && Grid_ptr[iPlusSideTimesTwo+2] == 'X')
                    {
                        humanWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [?] [?] [Y] [Y]   This illustration shows that checking only at Y will suffice
                // [?] [?] [Y] [Y]   for this specific check in screening for all Top Right --> Down Left
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Left --> Down Right is done mirrored
                // [?] [?] [?] [?]   This because all other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (i % Side > 1 && i + Side*2-2 < GridSize)
                {
                    if (Grid_ptr[i+Side-1] == 'X' && Grid_ptr[i+Side*2-2] == 'X')
                    {
                        humanWin = true; 
                        break;
                    }
                }
            } //end if arrayvalue is 'X'
        } //end for each value in array
    } //end if currentMove 'H'
    else if (currentMove == 'C')
    {
        //Check for human win code
        //Check all array slots for an occurence of 'X'
        for(USHORT i = 0; i < GridSize; i++)
        {   
            //Local stack variables, optimizations for iterations in loops and if statements,
            //also for readability, this is (only efficient and) done only when it is guaranteed
            //to be used in every for jump. 
            USHORT iModSide = i % Side;
            USHORT SideMinTwo = Side - 2;
            USHORT SidePlusTwo = Side + 2;
            USHORT iPlusSide = i + Side;
            USHORT iPlusSideTimesTwo = i + Side * 2;
            USHORT iPlusOne = i + 1;
            USHORT iPlusTwo = i + 2;

            //If an X is found evaluate a win scenario
            if (Grid_ptr[i] == 'O')
            {
                //For each row -->
                if (iModSide < SideMinTwo)
                {
                    //Check horizontal win from left to right
                    if (Grid_ptr[i + 1] == 'O' && Grid_ptr[i + 2] == 'O')
                    {
                        computerWin = true;
                        break;
                    }
                }

                //For the two values under the 'O' (colomn wise) check for 'O''O'
                if (iPlusSideTimesTwo < GridSize)
                {
                    if(Grid_ptr[iPlusSide] == 'O' && Grid_ptr[iPlusSideTimesTwo] == 'O')
                    {
                        computerWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [X] [X] [?] [?]   This illustration shows that checking only at X will suffice
                // [X] [X] [?] [?]   for this specific check in screening for all Top Left --> Down Right
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Right --> Down Left is done mirrored
                // [?] [?] [?] [?]   All other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (iPlusSideTimesTwo < GridSize && iModSide < SideMinTwo)
                {
                    if (Grid_ptr[i+Side+1] == 'O' && Grid_ptr[iPlusSideTimesTwo+2] == 'O')
                    {
                        computerWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [?] [?] [Y] [Y]   This illustration shows that checking only at Y will suffice
                // [?] [?] [Y] [Y]   for this specific check in screening for all Top Right --> Down Left
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Left --> Down Right is done mirrored
                // [?] [?] [?] [?]   This because all other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (iPlusSideTimesTwo+2 < GridSize && iModSide < SidePlusTwo)
                {
                    if (Grid_ptr[i+Side-1] == 'O' && Grid_ptr[i+Side*2-2] == 'O')
                    {
                        computerWin = true; 
                        break;
                    }
                }
            } //end if arrayvalue is 'O'
        } //end for each value in array
    }// else if currentMove 'C'
} //end method
//useAI(char* Grid_ptr) {  }

//weighGrid (char* Grid_ptr)  { for (USHORT i = 0; i < GridSize(find out); i++) {}  }


void PrintGrid(char* Grid_ptr, USHORT GridWidth, USHORT GridHeight, USHORT GridSize)
{
    //Abort this method if the Grid is not Square
    if (GridWidth != GridHeight)
    {
        cout << "Warning! \n\nGrid is not square. This method will likely fail!" << endl;
        cout << "Aborting method!" << endl;
        cout << "Press a key to return to program";         
    }
    else
    {
        //Since this code block's applicable to a square grid
        //Width or Height is not relevant, both should work
        //I have chosen to stick with Width everywhere.         

        USHORT rowStart = 0;
        USHORT rowEnd = GridWidth-1;
        USHORT passRowCounter = 1;
        USHORT Side = GridSize / GridHeight;

        for(USHORT i = 0; i < Side; i++)
        {   
            //GO TO NEXT ROW CODE
            rowEnd = Side * passRowCounter;
            passRowCounter++;               
            //PRINT ALL IN THIS ROW
            for (USHORT j = rowStart; j < rowEnd; j++)
            {
                cout << Grid_ptr[j];

            }
            rowStart = rowEnd;
            cout << "\n";
        }
    }
}

void useAI(char* Grid_ptr, USHORT GridSize, USHORT GridWidth)
{
    //Check all values in the array
    //If the value is '?' weigh the priority
    //else continue

    //Weighing the priority
    //If ('O' Present in legal ranges) add prio +1  

    //The AI Will function on this concept
    //All array slots have a weight, the highest weight means the best position
    //From top prio to lowest prio that means -->
    //WIN IN ONE MOVE (weight + 50)
    //NOT LOSE IN ONE MOVE (weight + 15) 
    //BLOCK ENEMY + LINK UP OWN ( Equal prio but stacks so both matter ) weight +1

    //These weights are determined using 8 directional vectors sprouting from all 'X' and 'O' locations in the grid
    //In it's path if it encounters on loc 1 'X' loc 2 + weight = 50 , and vice versa, else +1 for all 8 vectors

    //Create a weightgrid to store the data
    USHORT* WeightGrid_ptr = new USHORT[GridSize];  
    USHORT* fattest_ptr = new USHORT(0);
    USHORT* fattestIndex_ptr = new USHORT(0);

    USHORT Side = GridWidth;

    //Suggestion for optimization , make a forumula table to play all 8 vectors instead
    //Per vector u need Condition for the direction first space and next space. 24 statements in a list
    //A bit complex and harder to read so for now went the east 8 vectors copy pasting. But aware of the
    //solution none-the-less! Unfortunatly though it seems like a maze of code, it is well documented and
    //it's length is over 50% due to optimizations.

    for(USHORT i = 0; i < GridSize; i++)
    {
        if (Grid_ptr[i] == 'X')
        {
            //CHECK X --> Mid Right Vector
            //If within allowed parameters
            if(i % Side < Side-2)
            {
                if(Grid_ptr[i+1] == '?' && Grid_ptr[i+2] == '?')
                { 
                    WeightGrid_ptr[i+1] += 1; 
                    WeightGrid_ptr[i+2] += 1;
                }
                else if(Grid_ptr[i+1] == 'X')
                {
                    WeightGrid_ptr[i+2] += 15;
                }
                else if (Grid_ptr[i+2] == 'X')
                {
                    WeightGrid_ptr[i+1] += 15;
                }
            }
            //CHECK X --> Down Right Vector
            //If within allowed parameters
            if (i % Side < Side -2 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side+1] == '?' && Grid_ptr[i+Side*2+2] == '?')
                { 
                    WeightGrid_ptr[i+Side+1] += 1;
                    WeightGrid_ptr[i+Side*2+2] += 1;
                }
                else if(Grid_ptr[i+Side+1] == 'X')
                {
                    WeightGrid_ptr[i+Side*2+2] += 15;
                }
                else if (Grid_ptr[i+Side*2+2] == 'X')
                {
                    WeightGrid_ptr[i+Side+1] += 15;
                }
            }
            //CHECK X --> Down Mid Vector
            //If within allowed paramaters
            if (i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side] == '?' && Grid_ptr[i+Side*2] == '?')
                {
                    WeightGrid_ptr[i+Side] += 1;
                    WeightGrid_ptr[i+Side*2] += 1;
                }
                else if (Grid_ptr[i+Side] == 'X')
                {
                    WeightGrid_ptr[i+Side*2] += 15;
                }
                else if (Grid_ptr[i+Side*2] == 'X')
                {
                    WeightGrid_ptr[i+Side] += 15;
                }
            }
            //CHECK X --> Down Left Vector
            //If within allowed paramaters
            if(i % Side > 1 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i + Side*2-1] == '?' && i + Side*2-2 == '?')
                {
                    WeightGrid_ptr[i+Side*2-1] += 1;
                    WeightGrid_ptr[i+Side*2-2] += 1;
                }
                else if(Grid_ptr[i + Side*2-2] == 'X')
                {
                    WeightGrid_ptr[i+Side*2-1] += 15;
                }
                else if(Grid_ptr[i+Side*2-1] == 'X')
                {
                    WeightGrid_ptr[i+Side*2-2] += 15;
                }
            }
            //CHECK X --> Mid Left Vector
            //If within allowed parameters
            if(i % Side > 1)
            {
                if (Grid_ptr[i-1] == '?' && Grid_ptr[i-2] == '?')
                {
                    WeightGrid_ptr[i-1] += 1;
                    WeightGrid_ptr[i-2] += 1;
                }
                else if(Grid_ptr[i-1] == 'X')
                {
                    WeightGrid_ptr[i-2] += 15;
                }
                else if(Grid_ptr[i-2] == 'X')
                {
                    WeightGrid_ptr[i-1] += 15;
                }
            }
            //CHECK X --> Top Left Vector
            //If within allowed parameters
            if( (i) % (Side > 1) && i > Side*2)
            {
                if (Grid_ptr[i-Side-1] == '?' && Grid_ptr[i-Side*2-2] == '?') 
                {
                    WeightGrid_ptr[i-Side-1] += 1;
                    WeightGrid_ptr[i-Side*2-2] += 1;
                }
                else if (Grid_ptr[i-Side-1] == 'X') 
                {
                    WeightGrid_ptr[i-Side*2-2] += 15;
                }
                else if (Grid_ptr[i-Side*2-2] == 'X') 
                {
                    WeightGrid_ptr[i-Side-1] += 15;
                }
            }
            //CHECK X --> Mid Top Vector
            //If within allowed parameters
            if (i > Side*2)
            {
                if(Grid_ptr[i + Side] == '?' && Grid_ptr[i + Side*2] == '?')
                {
                    WeightGrid_ptr[i + Side] += 1;
                    WeightGrid_ptr[i + Side*2] += 1;
                }
                else if(Grid_ptr[i + Side] == 'X')
                {
                    WeightGrid_ptr[i + Side*2] += 15;
                }
                else if (Grid_ptr[i + Side*2] == 'X')
                {
                    WeightGrid_ptr[i + Side] += 15;
                }
            }
        } //end if 'X' detected
        else if (Grid_ptr[i] == 'O')
        {
            //CHECK 8 VECTORS
            //Add weights

            //CHECK O --> Mid Right Vector
            //If within allowed parameters
            if(i % Side < Side-2)
            {
                if(Grid_ptr[i+1] == '?' && Grid_ptr[i+2] == '?')
                { 
                    WeightGrid_ptr[i+1] += 1; 
                    WeightGrid_ptr[i+2] += 1;
                }
                else if(Grid_ptr[i+1] == 'O')
                {
                    WeightGrid_ptr[i+2] += 50;
                }
                else if (Grid_ptr[i+2] == 'O')
                {
                    WeightGrid_ptr[i+1] += 50;
                }

            }

            //CHECK O --> Down Right Vector
            //If within allowed parameters
            if (i % Side < Side -2 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side+1] == '?' && Grid_ptr[i+Side*2+2] == '?')
                { 
                    WeightGrid_ptr[i+Side+1] += 1;
                    WeightGrid_ptr[i+Side*2+2] += 1;
                }
                else if(Grid_ptr[i+Side+1] == 'O')
                {
                    WeightGrid_ptr[i+Side*2+2] += 50;
                }
                else if (Grid_ptr[i+Side*2+2] == 'O')
                {
                    WeightGrid_ptr[i+Side+1] += 50;
                }
            }

            //CHECK O --> Down Mid Vector
            //If within allowed paramaters
            if (i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side] == '?' && Grid_ptr[i+Side*2] == '?')
                {
                    WeightGrid_ptr[i+Side] += 1;
                    WeightGrid_ptr[i+Side*2] += 1;
                }
                else if (Grid_ptr[i+Side] == 'O')
                {
                    WeightGrid_ptr[i+Side*2] += 50;
                }
                else if (Grid_ptr[i+Side*2] == 'O')
                {
                    WeightGrid_ptr[i+Side] += 50;
                }
            }

            //CHECK O --> Down Left Vector
            //If within allowed paramaters
            if(i % Side > 1 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i + Side*2-1] == '?' && i + Side*2-2 == '?')
                {
                    WeightGrid_ptr[i+Side*2-1] += 1;
                    WeightGrid_ptr[i+Side*2-2] += 1;
                }
                else if(Grid_ptr[i + Side*2-2] == 'O')
                {
                    WeightGrid_ptr[i+Side*2-1] += 50;
                }
                else if(Grid_ptr[i+Side*2-1] == 'O')
                {
                    WeightGrid_ptr[i+Side*2-2] += 50;
                }
            }

            //CHECK O --> Mid Left Vector
            //If within allowed parameters
            if(i % Side > 1)
            {
                if (Grid_ptr[i-1] == '?' && Grid_ptr[i-2] == '?')
                {
                    WeightGrid_ptr[i-1] += 1;
                    WeightGrid_ptr[i-2] += 1;
                }
                else if(Grid_ptr[i-1] == 'O')
                {
                    WeightGrid_ptr[i-2] += 50;
                }
                else if(Grid_ptr[i-2] == 'O')
                {
                    WeightGrid_ptr[i-1] += 50;
                }
            }

            //CHECK O --> Top Left Vector
            //If within allowed parameters
            if( (i) & (Side > 1) && i > Side*2)
            {
                if (Grid_ptr[i-Side-1] == '?' && Grid_ptr[i-Side*2-2] == '?') 
                {
                    WeightGrid_ptr[i-Side-1] += 1;
                    WeightGrid_ptr[i-Side*2-2] += 1;
                }
                else if (Grid_ptr[i-Side-1] == 'O') 
                {
                    WeightGrid_ptr[i-Side*2-2] += 50;
                }
                else if (Grid_ptr[i-Side*2-2] == 'O') 
                {
                    WeightGrid_ptr[i-Side-1] += 50;
                }
            }

            //CHECK O --> Mid Top Vector
            //If within allowed parameters
            if (i > Side*2)
            {
                if(Grid_ptr[i + Side] == '?' && Grid_ptr[i + Side*2] == '?')
                {
                    WeightGrid_ptr[i + Side] += 1;
                    WeightGrid_ptr[i + Side*2] += 1;
                }
                else if(Grid_ptr[i + Side] == 'O')
                {
                    WeightGrid_ptr[i + Side*2] += 50;
                }
                else if (Grid_ptr[i + Side*2] == 'O')
                {
                    WeightGrid_ptr[i + Side] += 50;
                }
            }
        }
    } // end for scan 'X' 'O'

    //Get highest value from weightgrid, add an 'O' to that position, end method automatically
    for (USHORT q = 0; q < GridSize; q++)
    {
        if (Grid_ptr[q] == '?')
        {
            //If a better spot is found
            if (WeightGrid_ptr[q] > *fattest_ptr)
            {
                *fattest_ptr = WeightGrid_ptr[q];
                *fattestIndex_ptr = q;
            }
        }
    }

    Grid_ptr[*fattestIndex_ptr] = 'O';

    //SAFE DELETE POINTER WeightGrid_ptr
    if (WeightGrid_ptr != NULL)
    {
        delete[] WeightGrid_ptr;
        WeightGrid_ptr = NULL;      
    }
    //SAFE DELETE POINTER fattest_ptr
    if (fattest_ptr != NULL)
    {
        delete fattest_ptr;
        fattest_ptr = NULL;     
    }
    //SAFE DELETE POINTER fattestIndex_ptr
    if (fattestIndex_ptr != NULL)
    {
        delete fattestIndex_ptr;
        fattestIndex_ptr = NULL;        
    }

}

int _tmain(int argc, _TCHAR* argv[])
{
    //& adress off       |-|  &x  = 0x?
    //* value pointed by |-|  a = *b

    //Make the required variables on the heap
    USHORT GridHeight = 0;
    USHORT GridWidth  = 0;
    USHORT GridSize = 0;
    USHORT moveCounter = 0;



    char currentMove;

    USHORT input;
    //bool* humanWin_ptr = new bool(false);
    //bool* computerWin_ptr = new bool(false);

    bool humanWin_ptr = false;
    bool computerWin_ptr = false;

    bool Draw = false;

    cout << "A challanger has arrived!" << endl;

    //WARNING FOR THIS BLOCK! Special condition on for loop!
    for(;;)
    {
        cout << "Please state the width for the grid \n";
        scanf_s("%hu", &input);
        if (input > 2 && input < 20)
        {
            GridWidth = input;
            break; //CRITICAL CODE
        }
        else
        {
            cout << "Input was not correct, please state a number between 3 and 20 \n\n";
            cout << "Example of correct input '3' (without quotes) \n";         
        }
    }

    //WARNING FOR THIS BLOCK! Special condition on for loop!
    for(;;)
    {
        cout << "Please state the height for the grid \n";  
        scanf_s("%hu", &input);
        if (input > 2 && input < 20)
        {
            GridHeight = input;
            break; //CRITICAL CODE
        }
        else
        {
            cout << "Input was not correct, please state a number between 3 and 20 \n\n";
            cout << "Example of correct input '3' (without quotes) \n";
        }
    }

    cout << "You have succesfully filled in the paperwork to create the Grid" << endl;

    GridSize = GridHeight * GridWidth;
    cout << "The total GridSize is " << GridSize << " tiles in size" << endl;

    //if (GridWidth != GridHeigth)
    //{
    //  cout << "Warning! \n\nGrid is not square. Program may run irregularly!";
    //  cout << "Close the program or press a key to continue";
    //  scanf();
    //}

    //Note: pointer to a Grid object on the heap
    char* Grid_ptr = new char[GridSize];


    //Initialize Grid as empty
    for (USHORT i = 0; i < GridSize; i++)
    {
        Grid_ptr[i] = '?';      
    }



    //Visualize this step
    cout << "Grid created as empty Grid" << endl;
    cout << endl;

    cout << "Please read the following introduction if you wish for an explanation of the game" << endl;
    cout << "You will be reffered to as Player One equally so the opponent as AI" << endl;
    cout << "You always start with the first move" << endl;
    cout << "The condition for victory is a line of X X X (3 total) in a single line, colomn or a diagonal line across the Grid" << endl;
    cout << "Turns are exchanged per move 1 : 1, there are no time limits so use all you need" << endl;
    cout << "Player One can not lose this 3x3 Grid game when the best option is always chosen" << endl;
    cout << "Consider playing a larger field if you wish to win, Best of luck!" << endl;
    cout << "The grid is filled in like this!" << endl;

    PrintGrid(Grid_ptr, GridWidth, GridHeight, GridSize);

    while(humanWin_ptr == false && computerWin_ptr == false && Draw == false)
    {
        cout << "Players One's Turn! \n";
        cout << "Please fill in the number your X";     

        currentMove = 'H';
        for(;;)
        {
            scanf_s("%i" , &input);
            if (Grid_ptr[input] == 'X' || Grid_ptr[input] == 'O')
            {
                cout << "That space is already taken ,try another";
            }
            else
            {
                Grid_ptr[input] = 'X';
                moveCounter++;
                break;
            }
        }

        cout << '\n';
        PrintGrid(Grid_ptr, GridWidth, GridHeight, GridSize);
        CheckForWin(Grid_ptr, GridSize, GridWidth, humanWin_ptr, computerWin_ptr, currentMove);

        cout << "AI is making a move!" << endl;

        currentMove = 'C';
        useAI(Grid_ptr, GridSize, GridWidth);
        cout << '\n';
        PrintGrid(Grid_ptr, GridWidth, GridHeight, GridSize);
        CheckForWin(Grid_ptr, GridSize, GridWidth, humanWin_ptr, computerWin_ptr, currentMove);

        if (humanWin_ptr)
        {
            cout << "Congratulations you have won the game! \n";
            char c;
            puts ("Enter any text. Include a Space ('.') in a sentence to exit: \n");
            do 
            {
                c=getchar();
                putchar (c);
            } 
            while (c != ' ');   
        }
        else if (computerWin_ptr)
        {
            cout << "The computer won this match, better luck next time! \n";
            char c;
            puts ("Enter any text. Include a Space ('.') in a sentence to exit: \n");
            do 
            {
                c=getchar();
                putchar (c);
            } 
            while (c != ' ');               
        }

        if (moveCounter >= GridSize)
        {
            Draw = true;
            cout << "The game was a draw, good fighting!";
        }
    }

    //int ch = 0;
    //ch = _getch();
    //wint_t _getwch( void );


    //SAFE DELETE POINTER GRID
    if (Grid_ptr != NULL)
    { 
         delete[] Grid_ptr;
         Grid_ptr = NULL;       
    }
    /*
    //SAFE DELETE POINTER Human Win
    if (humanWin_ptr != NULL)
    {
        delete humanWin_ptr;
        humanWin_ptr = NULL;        
    }
    //SAFE DELETE POINTER Computer Win
    if (computerWin_ptr != NULL)
    {   
        delete computerWin_ptr;
        computerWin_ptr = NULL;     
    }*/



    return 0;
}

I made a game like that , the first thing I ever made in C++ actually ( Who needs hello world :P)

And everyone can use it if they want.

Just don't forget it's my first C++ thing and it's definatly not properly coded :P but it has some nice C++ things like that in it. But there's a 100% optimized search algorithm in there that checks the absolute least amount of required permutation to check three in a row win conditions with heavy commenting and ASCII art. That could be quite usefull.

Oh almost forgot the mention, It's a console application thingy (black screen DOS envi ,whatever it's called). It has an AI that (if this is my latest version) Should do pretty well. AND the grid is dynamically built (which was the hard part) U can play 3 in a row, but with a max of 20x20 grid ( lame game I found out, much more fun as 4 in a row with gravity )

Here you go:

// DrieOpEenRij.cpp : Defines the entry point for the console application.

     #include "stdafx.h"
     #include <iostream>
     #include <string>
     #include <typeinfo>

    using namespace std;

    typedef unsigned short USHORT;

    //USE ONLY IN A SQUARE GRID
    //This method checks a win for the minimimum amount of spaces covering 100% amount of the grid
    //It has 100% coverage and close to 0% overhead, discrimination between who to check for is required and
    //so currentMove char is required to check for win on 'H' human and 'C' Computer
    void CheckForWin(const char* Grid_ptr , const USHORT GridSize , const USHORT GridWidth ,bool &humanWin, bool &computerWin, const char currentMove)
    {
        //check for an x from 1-end of array
        //for all x's check if that makes a 3 line once per linetype
        //check for horizontal win (dont get overhead on edges)

    //A non square grid will have been detected by now
    const USHORT rowStart = 0;
    const USHORT rowEnd = GridWidth-1;
    USHORT passRowCounter = 1;
    const USHORT Side = GridWidth;

    const USHORT cond1 = rowEnd-2;
    const USHORT cond2 = GridSize-Side*2;   

    //Check for all human win options ( after a human move )
    if (currentMove == 'H')
    {
        //Check for human win code
        //Check all array slots for an occurence of 'X'
        for(USHORT i = 0; i < GridSize; i++)
        {   
            //Local stack variables, optimizations for iterations in loops and if statements,
            //also for readability, this is (only efficient and) done only when it is guaranteed
            //to be used in every for jump. 
            USHORT iModSide = i % Side;
            USHORT SideMinTwo = Side - 2;
            USHORT SidePlusTwo = Side + 2;
            USHORT iPlusSide = i + Side;
            USHORT iPlusSideTimesTwo = i + Side * 2;
            USHORT iPlusOne = i + 1;
            USHORT iPlusTwo = i + 2;

            //If an X is found evaluate a win scenario
            if (Grid_ptr[i] == 'X')
            {
                //For each row -->
                if (iModSide < SideMinTwo)
                {
                    //Check horizontal win from left to right
                    if (Grid_ptr[i + 1] == 'X' && Grid_ptr[i + 2] == 'X')
                    {
                        humanWin = true;
                        break;
                    }
                }

                //For the two values under the 'X' (colomn wise) check for 'X''X'
                if (iPlusSideTimesTwo < GridSize)
                {
                    if(Grid_ptr[iPlusSide] == 'X' && Grid_ptr[iPlusSideTimesTwo] == 'X')
                    {
                        humanWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [X] [X] [?] [?]   This illustration shows that checking only at X will suffice
                // [X] [X] [?] [?]   for this specific check in screening for all Top Left --> Down Right
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Right --> Down Left is done mirrored
                // [?] [?] [?] [?]   All other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (iPlusSideTimesTwo < GridSize && iModSide < SideMinTwo)
                {
                    if (Grid_ptr[i+Side+1] == 'X' && Grid_ptr[iPlusSideTimesTwo+2] == 'X')
                    {
                        humanWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [?] [?] [Y] [Y]   This illustration shows that checking only at Y will suffice
                // [?] [?] [Y] [Y]   for this specific check in screening for all Top Right --> Down Left
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Left --> Down Right is done mirrored
                // [?] [?] [?] [?]   This because all other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (i % Side > 1 && i + Side*2-2 < GridSize)
                {
                    if (Grid_ptr[i+Side-1] == 'X' && Grid_ptr[i+Side*2-2] == 'X')
                    {
                        humanWin = true; 
                        break;
                    }
                }
            } //end if arrayvalue is 'X'
        } //end for each value in array
    } //end if currentMove 'H'
    else if (currentMove == 'C')
    {
        //Check for human win code
        //Check all array slots for an occurence of 'X'
        for(USHORT i = 0; i < GridSize; i++)
        {   
            //Local stack variables, optimizations for iterations in loops and if statements,
            //also for readability, this is (only efficient and) done only when it is guaranteed
            //to be used in every for jump. 
            USHORT iModSide = i % Side;
            USHORT SideMinTwo = Side - 2;
            USHORT SidePlusTwo = Side + 2;
            USHORT iPlusSide = i + Side;
            USHORT iPlusSideTimesTwo = i + Side * 2;
            USHORT iPlusOne = i + 1;
            USHORT iPlusTwo = i + 2;

            //If an X is found evaluate a win scenario
            if (Grid_ptr[i] == 'O')
            {
                //For each row -->
                if (iModSide < SideMinTwo)
                {
                    //Check horizontal win from left to right
                    if (Grid_ptr[i + 1] == 'O' && Grid_ptr[i + 2] == 'O')
                    {
                        computerWin = true;
                        break;
                    }
                }

                //For the two values under the 'O' (colomn wise) check for 'O''O'
                if (iPlusSideTimesTwo < GridSize)
                {
                    if(Grid_ptr[iPlusSide] == 'O' && Grid_ptr[iPlusSideTimesTwo] == 'O')
                    {
                        computerWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [X] [X] [?] [?]   This illustration shows that checking only at X will suffice
                // [X] [X] [?] [?]   for this specific check in screening for all Top Left --> Down Right
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Right --> Down Left is done mirrored
                // [?] [?] [?] [?]   All other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (iPlusSideTimesTwo < GridSize && iModSide < SideMinTwo)
                {
                    if (Grid_ptr[i+Side+1] == 'O' && Grid_ptr[iPlusSideTimesTwo+2] == 'O')
                    {
                        computerWin = true; 
                        break;
                    }
                }

                //CHECK FOR DIAGONAL WIN FROM TOP LEFT TO DOWN RIGHT IN ALL POSSIBLE+LEGAL SLOTS!
                // [?] [?] [Y] [Y]   This illustration shows that checking only at Y will suffice
                // [?] [?] [Y] [Y]   for this specific check in screening for all Top Right --> Down Left
                // [?] [?] [?] [?]   diagonal wins, similarly the Top Left --> Down Right is done mirrored
                // [?] [?] [?] [?]   This because all other wins using this vector are impossible!
                // Using this amount of conditions to find it saves a lot of searching and with it time
                if (iPlusSideTimesTwo+2 < GridSize && iModSide < SidePlusTwo)
                {
                    if (Grid_ptr[i+Side-1] == 'O' && Grid_ptr[i+Side*2-2] == 'O')
                    {
                        computerWin = true; 
                        break;
                    }
                }
            } //end if arrayvalue is 'O'
        } //end for each value in array
    }// else if currentMove 'C'
} //end method
//useAI(char* Grid_ptr) {  }

//weighGrid (char* Grid_ptr)  { for (USHORT i = 0; i < GridSize(find out); i++) {}  }


void PrintGrid(char* Grid_ptr, USHORT GridWidth, USHORT GridHeight, USHORT GridSize)
{
    //Abort this method if the Grid is not Square
    if (GridWidth != GridHeight)
    {
        cout << "Warning! \n\nGrid is not square. This method will likely fail!" << endl;
        cout << "Aborting method!" << endl;
        cout << "Press a key to return to program";         
    }
    else
    {
        //Since this code block's applicable to a square grid
        //Width or Height is not relevant, both should work
        //I have chosen to stick with Width everywhere.         

        USHORT rowStart = 0;
        USHORT rowEnd = GridWidth-1;
        USHORT passRowCounter = 1;
        USHORT Side = GridSize / GridHeight;

        for(USHORT i = 0; i < Side; i++)
        {   
            //GO TO NEXT ROW CODE
            rowEnd = Side * passRowCounter;
            passRowCounter++;               
            //PRINT ALL IN THIS ROW
            for (USHORT j = rowStart; j < rowEnd; j++)
            {
                cout << Grid_ptr[j];

            }
            rowStart = rowEnd;
            cout << "\n";
        }
    }
}

void useAI(char* Grid_ptr, USHORT GridSize, USHORT GridWidth)
{
    //Check all values in the array
    //If the value is '?' weigh the priority
    //else continue

    //Weighing the priority
    //If ('O' Present in legal ranges) add prio +1  

    //The AI Will function on this concept
    //All array slots have a weight, the highest weight means the best position
    //From top prio to lowest prio that means -->
    //WIN IN ONE MOVE (weight + 50)
    //NOT LOSE IN ONE MOVE (weight + 15) 
    //BLOCK ENEMY + LINK UP OWN ( Equal prio but stacks so both matter ) weight +1

    //These weights are determined using 8 directional vectors sprouting from all 'X' and 'O' locations in the grid
    //In it's path if it encounters on loc 1 'X' loc 2 + weight = 50 , and vice versa, else +1 for all 8 vectors

    //Create a weightgrid to store the data
    USHORT* WeightGrid_ptr = new USHORT[GridSize];  
    USHORT* fattest_ptr = new USHORT(0);
    USHORT* fattestIndex_ptr = new USHORT(0);

    USHORT Side = GridWidth;

    //Suggestion for optimization , make a forumula table to play all 8 vectors instead
    //Per vector u need Condition for the direction first space and next space. 24 statements in a list
    //A bit complex and harder to read so for now went the east 8 vectors copy pasting. But aware of the
    //solution none-the-less! Unfortunatly though it seems like a maze of code, it is well documented and
    //it's length is over 50% due to optimizations.

    for(USHORT i = 0; i < GridSize; i++)
    {
        if (Grid_ptr[i] == 'X')
        {
            //CHECK X --> Mid Right Vector
            //If within allowed parameters
            if(i % Side < Side-2)
            {
                if(Grid_ptr[i+1] == '?' && Grid_ptr[i+2] == '?')
                { 
                    WeightGrid_ptr[i+1] += 1; 
                    WeightGrid_ptr[i+2] += 1;
                }
                else if(Grid_ptr[i+1] == 'X')
                {
                    WeightGrid_ptr[i+2] += 15;
                }
                else if (Grid_ptr[i+2] == 'X')
                {
                    WeightGrid_ptr[i+1] += 15;
                }
            }
            //CHECK X --> Down Right Vector
            //If within allowed parameters
            if (i % Side < Side -2 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side+1] == '?' && Grid_ptr[i+Side*2+2] == '?')
                { 
                    WeightGrid_ptr[i+Side+1] += 1;
                    WeightGrid_ptr[i+Side*2+2] += 1;
                }
                else if(Grid_ptr[i+Side+1] == 'X')
                {
                    WeightGrid_ptr[i+Side*2+2] += 15;
                }
                else if (Grid_ptr[i+Side*2+2] == 'X')
                {
                    WeightGrid_ptr[i+Side+1] += 15;
                }
            }
            //CHECK X --> Down Mid Vector
            //If within allowed paramaters
            if (i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side] == '?' && Grid_ptr[i+Side*2] == '?')
                {
                    WeightGrid_ptr[i+Side] += 1;
                    WeightGrid_ptr[i+Side*2] += 1;
                }
                else if (Grid_ptr[i+Side] == 'X')
                {
                    WeightGrid_ptr[i+Side*2] += 15;
                }
                else if (Grid_ptr[i+Side*2] == 'X')
                {
                    WeightGrid_ptr[i+Side] += 15;
                }
            }
            //CHECK X --> Down Left Vector
            //If within allowed paramaters
            if(i % Side > 1 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i + Side*2-1] == '?' && i + Side*2-2 == '?')
                {
                    WeightGrid_ptr[i+Side*2-1] += 1;
                    WeightGrid_ptr[i+Side*2-2] += 1;
                }
                else if(Grid_ptr[i + Side*2-2] == 'X')
                {
                    WeightGrid_ptr[i+Side*2-1] += 15;
                }
                else if(Grid_ptr[i+Side*2-1] == 'X')
                {
                    WeightGrid_ptr[i+Side*2-2] += 15;
                }
            }
            //CHECK X --> Mid Left Vector
            //If within allowed parameters
            if(i % Side > 1)
            {
                if (Grid_ptr[i-1] == '?' && Grid_ptr[i-2] == '?')
                {
                    WeightGrid_ptr[i-1] += 1;
                    WeightGrid_ptr[i-2] += 1;
                }
                else if(Grid_ptr[i-1] == 'X')
                {
                    WeightGrid_ptr[i-2] += 15;
                }
                else if(Grid_ptr[i-2] == 'X')
                {
                    WeightGrid_ptr[i-1] += 15;
                }
            }
            //CHECK X --> Top Left Vector
            //If within allowed parameters
            if( (i) % (Side > 1) && i > Side*2)
            {
                if (Grid_ptr[i-Side-1] == '?' && Grid_ptr[i-Side*2-2] == '?') 
                {
                    WeightGrid_ptr[i-Side-1] += 1;
                    WeightGrid_ptr[i-Side*2-2] += 1;
                }
                else if (Grid_ptr[i-Side-1] == 'X') 
                {
                    WeightGrid_ptr[i-Side*2-2] += 15;
                }
                else if (Grid_ptr[i-Side*2-2] == 'X') 
                {
                    WeightGrid_ptr[i-Side-1] += 15;
                }
            }
            //CHECK X --> Mid Top Vector
            //If within allowed parameters
            if (i > Side*2)
            {
                if(Grid_ptr[i + Side] == '?' && Grid_ptr[i + Side*2] == '?')
                {
                    WeightGrid_ptr[i + Side] += 1;
                    WeightGrid_ptr[i + Side*2] += 1;
                }
                else if(Grid_ptr[i + Side] == 'X')
                {
                    WeightGrid_ptr[i + Side*2] += 15;
                }
                else if (Grid_ptr[i + Side*2] == 'X')
                {
                    WeightGrid_ptr[i + Side] += 15;
                }
            }
        } //end if 'X' detected
        else if (Grid_ptr[i] == 'O')
        {
            //CHECK 8 VECTORS
            //Add weights

            //CHECK O --> Mid Right Vector
            //If within allowed parameters
            if(i % Side < Side-2)
            {
                if(Grid_ptr[i+1] == '?' && Grid_ptr[i+2] == '?')
                { 
                    WeightGrid_ptr[i+1] += 1; 
                    WeightGrid_ptr[i+2] += 1;
                }
                else if(Grid_ptr[i+1] == 'O')
                {
                    WeightGrid_ptr[i+2] += 50;
                }
                else if (Grid_ptr[i+2] == 'O')
                {
                    WeightGrid_ptr[i+1] += 50;
                }

            }

            //CHECK O --> Down Right Vector
            //If within allowed parameters
            if (i % Side < Side -2 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side+1] == '?' && Grid_ptr[i+Side*2+2] == '?')
                { 
                    WeightGrid_ptr[i+Side+1] += 1;
                    WeightGrid_ptr[i+Side*2+2] += 1;
                }
                else if(Grid_ptr[i+Side+1] == 'O')
                {
                    WeightGrid_ptr[i+Side*2+2] += 50;
                }
                else if (Grid_ptr[i+Side*2+2] == 'O')
                {
                    WeightGrid_ptr[i+Side+1] += 50;
                }
            }

            //CHECK O --> Down Mid Vector
            //If within allowed paramaters
            if (i + Side*2 < GridSize)
            {
                if (Grid_ptr[i+Side] == '?' && Grid_ptr[i+Side*2] == '?')
                {
                    WeightGrid_ptr[i+Side] += 1;
                    WeightGrid_ptr[i+Side*2] += 1;
                }
                else if (Grid_ptr[i+Side] == 'O')
                {
                    WeightGrid_ptr[i+Side*2] += 50;
                }
                else if (Grid_ptr[i+Side*2] == 'O')
                {
                    WeightGrid_ptr[i+Side] += 50;
                }
            }

            //CHECK O --> Down Left Vector
            //If within allowed paramaters
            if(i % Side > 1 && i + Side*2 < GridSize)
            {
                if (Grid_ptr[i + Side*2-1] == '?' && i + Side*2-2 == '?')
                {
                    WeightGrid_ptr[i+Side*2-1] += 1;
                    WeightGrid_ptr[i+Side*2-2] += 1;
                }
                else if(Grid_ptr[i + Side*2-2] == 'O')
                {
                    WeightGrid_ptr[i+Side*2-1] += 50;
                }
                else if(Grid_ptr[i+Side*2-1] == 'O')
                {
                    WeightGrid_ptr[i+Side*2-2] += 50;
                }
            }

            //CHECK O --> Mid Left Vector
            //If within allowed parameters
            if(i % Side > 1)
            {
                if (Grid_ptr[i-1] == '?' && Grid_ptr[i-2] == '?')
                {
                    WeightGrid_ptr[i-1] += 1;
                    WeightGrid_ptr[i-2] += 1;
                }
                else if(Grid_ptr[i-1] == 'O')
                {
                    WeightGrid_ptr[i-2] += 50;
                }
                else if(Grid_ptr[i-2] == 'O')
                {
                    WeightGrid_ptr[i-1] += 50;
                }
            }

            //CHECK O --> Top Left Vector
            //If within allowed parameters
            if( (i) & (Side > 1) && i > Side*2)
            {
                if (Grid_ptr[i-Side-1] == '?' && Grid_ptr[i-Side*2-2] == '?') 
                {
                    WeightGrid_ptr[i-Side-1] += 1;
                    WeightGrid_ptr[i-Side*2-2] += 1;
                }
                else if (Grid_ptr[i-Side-1] == 'O') 
                {
                    WeightGrid_ptr[i-Side*2-2] += 50;
                }
                else if (Grid_ptr[i-Side*2-2] == 'O') 
                {
                    WeightGrid_ptr[i-Side-1] += 50;
                }
            }

            //CHECK O --> Mid Top Vector
            //If within allowed parameters
            if (i > Side*2)
            {
                if(Grid_ptr[i + Side] == '?' && Grid_ptr[i + Side*2] == '?')
                {
                    WeightGrid_ptr[i + Side] += 1;
                    WeightGrid_ptr[i + Side*2] += 1;
                }
                else if(Grid_ptr[i + Side] == 'O')
                {
                    WeightGrid_ptr[i + Side*2] += 50;
                }
                else if (Grid_ptr[i + Side*2] == 'O')
                {
                    WeightGrid_ptr[i + Side] += 50;
                }
            }
        }
    } // end for scan 'X' 'O'

    //Get highest value from weightgrid, add an 'O' to that position, end method automatically
    for (USHORT q = 0; q < GridSize; q++)
    {
        if (Grid_ptr[q] == '?')
        {
            //If a better spot is found
            if (WeightGrid_ptr[q] > *fattest_ptr)
            {
                *fattest_ptr = WeightGrid_ptr[q];
                *fattestIndex_ptr = q;
            }
        }
    }

    Grid_ptr[*fattestIndex_ptr] = 'O';

    //SAFE DELETE POINTER WeightGrid_ptr
    if (WeightGrid_ptr != NULL)
    {
        delete[] WeightGrid_ptr;
        WeightGrid_ptr = NULL;      
    }
    //SAFE DELETE POINTER fattest_ptr
    if (fattest_ptr != NULL)
    {
        delete fattest_ptr;
        fattest_ptr = NULL;     
    }
    //SAFE DELETE POINTER fattestIndex_ptr
    if (fattestIndex_ptr != NULL)
    {
        delete fattestIndex_ptr;
        fattestIndex_ptr = NULL;        
    }

}

int _tmain(int argc, _TCHAR* argv[])
{
    //& adress off       |-|  &x  = 0x?
    //* value pointed by |-|  a = *b

    //Make the required variables on the heap
    USHORT GridHeight = 0;
    USHORT GridWidth  = 0;
    USHORT GridSize = 0;
    USHORT moveCounter = 0;



    char currentMove;

    USHORT input;
    //bool* humanWin_ptr = new bool(false);
    //bool* computerWin_ptr = new bool(false);

    bool humanWin_ptr = false;
    bool computerWin_ptr = false;

    bool Draw = false;

    cout << "A challanger has arrived!" << endl;

    //WARNING FOR THIS BLOCK! Special condition on for loop!
    for(;;)
    {
        cout << "Please state the width for the grid \n";
        scanf_s("%hu", &input);
        if (input > 2 && input < 20)
        {
            GridWidth = input;
            break; //CRITICAL CODE
        }
        else
        {
            cout << "Input was not correct, please state a number between 3 and 20 \n\n";
            cout << "Example of correct input '3' (without quotes) \n";         
        }
    }

    //WARNING FOR THIS BLOCK! Special condition on for loop!
    for(;;)
    {
        cout << "Please state the height for the grid \n";  
        scanf_s("%hu", &input);
        if (input > 2 && input < 20)
        {
            GridHeight = input;
            break; //CRITICAL CODE
        }
        else
        {
            cout << "Input was not correct, please state a number between 3 and 20 \n\n";
            cout << "Example of correct input '3' (without quotes) \n";
        }
    }

    cout << "You have succesfully filled in the paperwork to create the Grid" << endl;

    GridSize = GridHeight * GridWidth;
    cout << "The total GridSize is " << GridSize << " tiles in size" << endl;

    //if (GridWidth != GridHeigth)
    //{
    //  cout << "Warning! \n\nGrid is not square. Program may run irregularly!";
    //  cout << "Close the program or press a key to continue";
    //  scanf();
    //}

    //Note: pointer to a Grid object on the heap
    char* Grid_ptr = new char[GridSize];


    //Initialize Grid as empty
    for (USHORT i = 0; i < GridSize; i++)
    {
        Grid_ptr[i] = '?';      
    }



    //Visualize this step
    cout << "Grid created as empty Grid" << endl;
    cout << endl;

    cout << "Please read the following introduction if you wish for an explanation of the game" << endl;
    cout << "You will be reffered to as Player One equally so the opponent as AI" << endl;
    cout << "You always start with the first move" << endl;
    cout << "The condition for victory is a line of X X X (3 total) in a single line, colomn or a diagonal line across the Grid" << endl;
    cout << "Turns are exchanged per move 1 : 1, there are no time limits so use all you need" << endl;
    cout << "Player One can not lose this 3x3 Grid game when the best option is always chosen" << endl;
    cout << "Consider playing a larger field if you wish to win, Best of luck!" << endl;
    cout << "The grid is filled in like this!" << endl;

    PrintGrid(Grid_ptr, GridWidth, GridHeight, GridSize);

    while(humanWin_ptr == false && computerWin_ptr == false && Draw == false)
    {
        cout << "Players One's Turn! \n";
        cout << "Please fill in the number your X";     

        currentMove = 'H';
        for(;;)
        {
            scanf_s("%i" , &input);
            if (Grid_ptr[input] == 'X' || Grid_ptr[input] == 'O')
            {
                cout << "That space is already taken ,try another";
            }
            else
            {
                Grid_ptr[input] = 'X';
                moveCounter++;
                break;
            }
        }

        cout << '\n';
        PrintGrid(Grid_ptr, GridWidth, GridHeight, GridSize);
        CheckForWin(Grid_ptr, GridSize, GridWidth, humanWin_ptr, computerWin_ptr, currentMove);

        cout << "AI is making a move!" << endl;

        currentMove = 'C';
        useAI(Grid_ptr, GridSize, GridWidth);
        cout << '\n';
        PrintGrid(Grid_ptr, GridWidth, GridHeight, GridSize);
        CheckForWin(Grid_ptr, GridSize, GridWidth, humanWin_ptr, computerWin_ptr, currentMove);

        if (humanWin_ptr)
        {
            cout << "Congratulations you have won the game! \n";
            char c;
            puts ("Enter any text. Include a Space ('.') in a sentence to exit: \n");
            do 
            {
                c=getchar();
                putchar (c);
            } 
            while (c != ' ');   
        }
        else if (computerWin_ptr)
        {
            cout << "The computer won this match, better luck next time! \n";
            char c;
            puts ("Enter any text. Include a Space ('.') in a sentence to exit: \n");
            do 
            {
                c=getchar();
                putchar (c);
            } 
            while (c != ' ');               
        }

        if (moveCounter >= GridSize)
        {
            Draw = true;
            cout << "The game was a draw, good fighting!";
        }
    }

    //int ch = 0;
    //ch = _getch();
    //wint_t _getwch( void );


    //SAFE DELETE POINTER GRID
    if (Grid_ptr != NULL)
    { 
         delete[] Grid_ptr;
         Grid_ptr = NULL;       
    }
    /*
    //SAFE DELETE POINTER Human Win
    if (humanWin_ptr != NULL)
    {
        delete humanWin_ptr;
        humanWin_ptr = NULL;        
    }
    //SAFE DELETE POINTER Computer Win
    if (computerWin_ptr != NULL)
    {   
        delete computerWin_ptr;
        computerWin_ptr = NULL;     
    }*/



    return 0;
}
故事↓在人 2024-10-07 20:50:48

你所要求的接缝是关于微观优化的。首先正确实施,然后分析/测量以发现瓶颈,然后思考如何改进。

由于这个问题非常笼统(并且没有示例和代码),我认为不可能有不同的答案。

What you are asking seams to be about micro optimization. First implement it right, then profile/measure to find bottlenecks, and then think how to improve.

Since the question is so general (and without the example and code), I do not think it is possible to answer differently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文