I have 2 separate boards for 2 players: X and O. Now I'd like to make sure if an entered position (int x, int y) is valid but I've got no idea of how should I convert it to bitboard representation and compare it with given board states and it's doing me head in. Also wrote a helper function to see the board states bin(). And is there a way to merge the X and O boards into one or should I keep the separate all board to check the game state?
#include <bits/stdc++.h>
using namespace std;
bool xmove = true;
const int win[] = { 0b111000000,
0b000111000,
0b000000111,
0b100100100,
0b010010010,
0b001001001,
0b100010001,
0b001010100 };
struct Board {
int b = 0b000000000;
};
int iswin(int x) {
for (size_t i = 0; i < 8; i++) {
if (win[i] == x) return 1;
}
return 0;
};
void bin(int x){
cout << "0b" + bitset<9>(x).to_string() << endl;
};
int main() {
Board x, o, all;
x.b |= 0b000000111;
o.b |= 0b000111000;
all.b = x.b | o.b;
bin(all.b);
cout << iswin(x.b);
return 0;
}
Well you can treat your bitstring as a flattened 2d array. To convert a 2d index into a 1d one you can simply do
x * width + y
So to set the matching position in the board you can do
int move = 1 << (x * 3 + y)
since a TicTacToe board is 3 wide and 3 tall. You can then check if there already is an X or O at that position with
if(x.b & move)
{
std::cout << "there already is and x at(" << x << ", " << y << ")";
}
To then add that position to the board if there is nothing there do
x.b |= move
Same thing for o.b. This is of course based on the assumption that your x and y start at 0.
Concerning your question of whether or not you can merge the two board. How would you even do that? A bit can only be 0 or 1 so there is no way to differentiate between 3 different states (nothing, X, O).
Related
I've begun into C++ from a heavy C background. This is my first program, which I'm using as a learning experience. A simple Snake Game. Everything runs smoothly, the only issue is that no matter what I do, after the players score reaches 4, the next bit of food is ALWAYS spawned inside of the wall, in the bottom left corner (1 row up from the bottom.) Running into it = Game Over.
This is running on a Linux server. I've tried messing with the border parameters, but I'm having a hard time figuring out what to change, because everything looks fine to my eyes. (Clearly something is not.)
I'm pasting the entire program below. It's quite short. I just need one of you guru's to read through/run the program and take me to school on something that's probably a simple fix. Pardon the excessive comments. I use these to teach (I have a following on pastebin as odd as that is to say)
/*
Snake Game - Tragedy
My First Program In C++
I'm Using This Much As A Learning Experience For Myself
And Would Like To Help Those Reading The Code For This Goofy Game
Understand C++ A Bit Better Too
Therefore I'm Trying To Explain As Much As Possible In Real Time
*/
#include <iostream> //Standard
#include <stdlib.h> //Standard
#include <unistd.h> //For POSIX Access
#include <sys/ioctl.h> //For Display Window, TTY Window (Console Window)
#include <termios.h> //For Line Buffering - See Below
#include <stdio.h> //Old Friend
#define CLRSCR "\e[1;1H\e[2J" //Command To Clear Terminal Screen - Change Accordingly
using namespace std; /*
A NameSpace Is Used As Additional Information
To Differentiate Between Similar Functions/Variables
That Have The Same Name In Different Libraries
Using 'namespace' You Can Define The Context
In Which Names Are Defined
Withoug Using The STD NameSpace, The Computer Will Try
To Call cout Or cin As If It Weren't Defined In A NameSpace
Trying To Call Something That Doesn't Exist = Error
So, Without Using namespace std; When You Write For Example:
'cout << value;' You'd Have To Write 'std::cout << value;''
*/
//Create Boundaries
const int width = 50;
const int height = 25;
const char block = 'o';
void ClearScreen(void)
{
cout << CLRSCR;
}
//Global Arrays For Data Records
int background[height][width]; // Background
int snake[50][2]; // Max Snake Length
int food[2] = {0,0}; // Snake Food
int score = 0; // Score
int snakelen = 3; // Snake Starting Length
int snakespeedx = 1; // Horizontal Speed
int snakespeedy = 1; // Vertical Speed
int lap = 200; // Waiting Time Betweeen Frames
//Declaring Global Temporary Variables To Save Memory
int px, py, nx, ny; //Postions
char k;
int h, w;
int x, y;
int movementx = snakespeedx; //Snake Movement
int movementy = 0; //Snake Movement
//Check For Keyboard Press
/*
Reference Link:
https://www.quora.com/With-which-function-can-I-replace-kbhit-in-C++-because-the-header-conio-h-doesnt-exist-in-linux
Ubuntu Users:
sudo apt-get install libncurses5-dev libncursesw5-dev
Life Saver:
http://www.flipcode.com/archives/_kbhit_for_Linux.shtml
*/
int bytesWaiting, i;
int _kbhit()
{
static const int STDIN = 0;
static bool initialized = false; //The Boolean Data Type Is Used To Declare A Variable Whose Value Will Be Set As True (1) Or False (0)
if (! initialized)
{
//Use Termios To Turn Off Line Buffering
termios term;
tcgetattr(STDIN, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN, TCSANOW, &term);
setbuf(stdin, NULL);
initialized = true;
}
ioctl(STDIN, FIONREAD, &bytesWaiting);
return bytesWaiting;
}
//Initialise background borders Onto Array
void initialise_background(void)
{
//int i;
// Insert Top Border
for(i=0; i<width; i++)
{
background[0][i]=1;
}
//Insert Left Border
for(i=0; i<height; i++)
{
background[i][0]=1;
}
//Insert Right Border
for(i=0; i<height; i++)
{
background[i][width-1]=1;
}
//Insert Bottom Border
for(i=0; i<width; i++)
{
background[height-1][i]=1;
}
}
//Initialise Snake Coordinates
void initialise_snake(void)
{
snake[0][0]=3; //Coordinates X
snake[0][1]=3; //Coordinates Y
snake[1][0]=3+1; //Coordinates X
snake[1][1]=3; //Coordinates Y
snake[2][0]=3+2; //Coordinates X
snake[2][1]=3; //Coordinates Y
snake[3][0]=3+3; //Coordinates X
snake[3][1]=3; //Coordinates Y
snake[4][0]=3+4; //Coordinates X
snake[4][1]=3; //Coordinates Y
}
//Update Snake
void update_snake_coordination(void)
{
//int px,py,nx, ny;
px = snake[0][0];
py = snake[0][1];
snake[0][0] = px + movementx;
snake[0][1] = py + movementy;
nx = snake[0][0];
ny = snake[0][1];
for(i=1; i<snakelen; i++)
{
nx = snake[i][0];
ny = snake[i][1];
snake[i][0] = px;
snake[i][1] = py;
px = nx;
py = ny;
}
}
//Install Snake Coordinates Into Background Array = ( 1 To Draw And 0 To Erase)
void draw_snake_in_background(const int rev)
{
//int x, y;
for(i = 0; i<snakelen; i++)
{
x = snake[i][0];
y = snake[i][1];
if((x!=0)&&(y!=0))
{
background[y][x] = rev;
}
}
}
//Print Array Frame
void print_array_frame(void)
{
for(h=0; h<height; h++)
{
for(w=0; w<width; w++)
{
i=background[h][w];
if(i==1)
{
cout << block;
}
else if (i == 2)
{
cout << "+";
}
else
{
cout << " ";
}
}
cout << endl;
}
}
//Update Loop
void mainloop(void)
{
ClearScreen();
draw_snake_in_background(1); // Install Snake
print_array_frame(); // Print Frame
draw_snake_in_background(0); // Uninstall Snake
}
//Waiting Function
void sleepcp(int milliseconds) // Cross-Platform Sleep Function
{
clock_t time_end;
time_end = clock() + milliseconds * CLOCKS_PER_SEC/1000;
while (clock() < time_end)
{
//
}
}
//Reaction To Keyboard Press
void reaction_on_keyboard(const char k)
{
if(k=='d'||k=='6')
{
//Right Turn
movementx = snakespeedx;
movementy = 0;
}
else if(k=='a'||k=='4')
{
//Left Turn
movementx = -snakespeedx;
movementy = 0;
}
else if(k=='w'||k=='8')
{
//Turn Up
movementx = 0;
movementy = -snakespeedy;
}
else if(k=='s'||k=='2')
{
//Turn Down
movementx = 0;
movementy = snakespeedy;
}
else if(k=='q'||k=='z'||k=='c')
{
cout << "[+] Exit Safely [+]"<<endl;
exit(0);
}
}
//Create Snake Food
void cook_food(void)
{
if (food[0]==0)
{
x = rand() % width + 1;
y = rand() % height + 1;
food[0] = x;
food[1] = y;
background[y][x] = 2;
}
}
//Check Snake & Food Status
void capture_food(void)
{
x = food[0];
y = food[1];
if ((x==snake[0][0])&&(y==snake[0][1]))
{
background[y][x] = 0;
food[0] = 0;
score ++;
snakelen ++;
cook_food();
}
}
//Check Snake is Not Touching Boundary
void check_over_lapping(void)
{
//int px,py;
px = snake[0][0];
py = snake[0][1];
if((px==0)||(px==(width-1))||(py==0)||(py==(height-1)))
{
cout << "[+] Game Over [+]" << endl;
exit(0);
}
}
//Loop
void loop(void)
{
int frame = 0;
x = 0;
y = 0;
while(x<500)
{
sleepcp(lap);
if(_kbhit()) //If Keyboard Pressed
{
cin >> k; //Character
reaction_on_keyboard(k);
}
mainloop(); //RUn Main Loop FUnction
update_snake_coordination();//Update Snake Coordinates
check_over_lapping(); //Check Snake Status
cook_food(); //Make Sure Food is Available
capture_food(); //Snake Eaten Food?
cout << "[ Frame : " << frame << " | Score : " << score << " ] "<< endl; //Print Status
frame ++;
}
}
//Main Trigger Function
main()
{
initialise_background(); //Install All Variables
initialise_snake(); //Install Snake data
loop(); //Run Update Loop
}
This is what happens when running the game:
oooooooooooooooooooooooooooooooooooooooooooooooooo
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o ooooooo o
o o
o o
o o
+<---Places Here Every Time o
oooooooooooooooooooooooooooooooooooooooooooooooooo
[ Frame : 169 | Score : 4 ]
Any Help or Input is greatly appreciated!
Your background array is height * width. When you place food into the array, you place it at rand() % width + 1 and rand() % height + 1, which have a range of 1 to width and 1 to height respectively. If you generate food at an x coordinate of width or a y coordinate of height, you will read outside the bounds of your background array. What is happening is that the seed your program is initialised with is generating food at an x position of width and because of the way memory is laid out that is the same array location as background[y + 1][0].
You probably want to change cook_food as follows:
void cook_food(void)
{
if (food[0]==0)
{
x = rand() % (width - 1) + 1;
y = rand() % (height - 1) + 1;
food[0] = x;
food[1] = y;
background[y][x] = 2;
}
}
I would note that this isn't really a C++ program, no matter what you're compiling it with. Your are using a very C style, storing data in a C way, and calling C standard library functions. You may want to read the isocpp C++ FAQ, which has some pointers to resources for people learning C++.
A C++ implementation would probably want to use the std::uniform_int_distribution class in the standard library, which makes it much clearer what your minimum and maximum values are for your food X and Y coordinates. You would also have 'Food' and 'Snake' objects that tracked their X and Y coordinates, rather than storing those values in arrays that you use directly.
EDIT: You've been asking some questions in the comments about collision detection for the snake. I believe this method will detect snake-on-snake collision given the code above:
bool is_snake_touching_itself() {
for (std::size_t i = 1; i < snakelen; ++i) {
if (snake[0][0] == snake[i][0] && snake[0][1] == snake[i][1]) {
return true;
}
}
return false;
}
I have 4 integer variables - x,y,z,t which could get values from an interval of integer values [a,b] ) ( the interval is a,a+1,a+2,...,b ).
I want to set a vector of distinct {x,y,z,t} values with the following rule:
2 quartets (x and y) are not equal if there exists at least one quartet value for which : x.i != y.i (i is one of the {x,y,z,t} value positions).
My current solution is extremely time consuming:
struct gim
{
int xx;
int yy;
int zz;
int tt;
}
vector<gim> v;
x=a;y=a;z=a;t=a;
nr_quartet=0;
gim g;
while(x<=b)
{
while(y<=b)
{
while(z<=b)
{
while(t<=b)
{
if(at least one of x,y,z,t is different)
{
nr_quartet++;
g.xx=x;
g.yy=y;
g.zz=z;
g.tt=t;
v.push_back(g);
cout << x << " " << y << " " << z << " " << t << "\n";
}
t++;
}
z++;
}
y++;
}
x++;
}
You can try something like this:
int actual_t = t;
int actual_z = z;
int actual_y = y;
int actual_x = x;
while(t<=b && z <=b && y<=b && x<=b)
{
if(at least one of x,y,z,t is different)
{
nr_quartet++;
v.emplace_back(x, y, z, t);
//cout << x << " " << y << " " << z << " " << t << "\n";
}
// For t
if(t==b)
{
t = 0;
}
else
{
t++;
}
actual_t = t;
// For z
if(z==b)
{
z = 0;
}
else if(/* incrementation condition for z */)
{
z++;
}
actual_z = z;
/* the same for y and x */
}
If you only need the number of elements of the set {(x,y,z,t) | ¬(x = y = z = t)}, then compute (b-a)**4 - (b-a); i.e. no need to iterate through all of them.
If you really need to fill a vector with all the combinations, well, you will have to iterate to add them all. The longest part will be memory allocations inside the std::vector, so pre-reserve or pre-resize with the number of elements since you can know it in advance.
As far as I've done is something which is consuming much time
What do you mean it is consuming a lot of time? What is your [a, b] range?
The code below is my source code that was part of a lab test that I recently took. I was counted off points because the program did not properly display the line and color it as it was supposed to. I found this incredible, as I had tested it for 3 points (to draw two lines), in order to save time on a timed test, and it works perfectly. The example input for the test was for 5 points (four lines). When I downloaded my code and tested it with 5 points, the graphical display does indeed go haywire, drawing seemingly random lines. I have debugged it, and after the third iteration (fourth time through the loop) of the first for loop where the program is collecting the x and y coordinates from the user, whatever is entered for the x coordinate value appears to be overwriting the loop control variableno_points[0], for no apparent reason. My thoughts are that the loop control variable, and the fourth x coordinate value are sharing an address somehow. As I said, I have already taken the test and received my grade, so I am not looking for a handout to cheat on anything. I simply am not able to understand why this occurring. Any help would be appreciated.
#include <iostream>
#include "graph1.h"
#include <cstdlib>
using namespace std;
// declaring prototypes
void getData(int* no_points, int* x, int* y, int* r, int* g, int* b);
void drawPolyLine(int* objects, int*x, int* y, int* no_points);
void colorPolyLine(int* objects, int* no_points, int r, int g, int b);
// declaring main
int main()
{
int no_points = NULL;
int x = NULL;
int y = NULL;
int r = NULL;
int g = NULL;
int b = NULL;
int objects[50] = {};
int again = 1;
do
{
displayGraphics();
clearGraphics();
getData(&no_points, &x, &y, &r, &g, &b);
drawPolyLine(objects, &x, &y, &no_points);
colorPolyLine(objects, &no_points, r, g, b);
cout << "Please enter a 0 to exit the program..." << endl;
cin >> again;
} while (again == 1);
return 0;
}
// declaring functions
void getData(int* no_points, int* x, int* y, int* r, int* g, int* b)
{
cout << "Enter # of points: " << endl;
cin >> *no_points;
cout << "Number of points entered is " << *no_points << endl;
cout << "Enter r/g/b colors..." << endl;
do
{
cout << "Enter a red value between 0 and 255 " << endl;
cin >> *r;
} while (*r < 0 || *r > 255);
do
{
cout << "Enter a green value between 0 and 255 " << endl;
cin >> *g;
} while (*g < 0 || *g > 255);
do
{
cout << "Enter a blue value between 0 and 255 " << endl;
cin >> *b;
} while (*b < 0 || *b > 255);
for (int i = 0; i < no_points[0]; i++)
{
cout << "Enter the x/y coord for Point #" << i + 1 << endl;
cin >> x[i]; cin >> y[i];
}
}
void drawPolyLine(int* objects, int* x, int* y, int* no_points)
{
for (int i = 0; i < no_points[0] -1; i++)
objects[i] = drawLine((x[i]), (y[i]), (x[i + 1]), (y[i + 1]), 3);
}
void colorPolyLine(int* objects, int* no_points, int r, int g, int b)
{
for (int i = 0; i < no_points[0] - 1; i++)
{
setColor(objects[i], r, g, b);
}
}
the x coordinate value appears to be overwriting the loop control variable "no_points[0]", for no apparent reason.
Well, for no reason that is apparent to you anyway.
In your main program you declare all your variables no_points, x, y, etc. as scalars, not arrays. That is, each variable accommodates one int. Your other functions treat the pointers to those variables (that you provide as arguments) as if they pointed into arrays at least no_points elements in length. Accessing elements past the first (at index 0) produces undefined behavior.
Although one cannot actually predict the outcome of undefined behavior from the code and the standard, memory corruption is a common outcome of the kind of incorrect code you present.
Lets say I have two AABB based areas, each area defined by two coordinates mins{x, y} and maxs{x, y}, I want to find the middle connection point between them.
Since my english is not good, I can't explain all with my words,
see the following picture for easier understanding:
http://i.*.com/WokivEe.png
All I need to find is the red point coordinates.
so If we move this into programming question, actual data structures would look like this:
struct Vec2D {
float x, y;
}
struct Rectangle {
Vec2D min;
Vec2D max;
}
Rectangle obj[2]
Anyone got an idea for an algorithm?
Along either the X or Y axis, sort the coordinates of the sides that touch into order. Then average the 2nd and 3rd ones in that list to find their midpoint. I hope this answers the question sufficiently.
Here is a little algorithm that first find which sides of the objects are closest, and then uses the 4 points along the common side to make a list, sorted along the common axis. The average of the 2 middle points of the sorted list are the answer. This will work for both horizontal and vertical sides. I added accessor functions to the data structures so that they can be indexed; e.g., for a Vec2D, coordinate(0) is the x value and coordinate(1) is the y value.
#include <math.h>
#include <iostream>
#include <limits>
struct Vec2D {
float x, y;
float coordinate(int axis)
{
return (axis & 1) ? y : x;
}
};
struct Rectangle {
Vec2D min;
Vec2D max;
Vec2D corner(int j)
{
return (j & 1) ? max : min;
}
// Get the other corner along the given axis
Vec2D along(int j, int ax)
{
Vec2D p = corner(j);
if (0 == ax)
{
p.x = corner(1-j).x;
}
else
{
p.y = corner(1-j).y;
}
return p;
}
};
using namespace std;
inline Vec2D* vp(const void* p)
{
return (Vec2D*) p;
}
static int compare_x(const void*a, const void*b)
{
if (vp(a)->x < vp(b)->x)
{
return -1;
}
else
if (vp(a)->x > vp(b)->x)
{
return 1;
}
return 0;
}
static int compare_y(const void*a, const void*b)
{
if (vp(a)->y < vp(b)->y)
{
return -1;
}
else
if (vp(a)->y > vp(b)->y)
{
return 1;
}
return 0;
}
int main(void) {
int ax; // axis index
int c0, c1;
float gap = numeric_limits<float>::max();
struct Rectangle obj[2] = {0,2,10,10,10,5,15,20};
struct
{
int ax,c0,c1;
} closest;
// Find out which sides are the closest to each other
for(ax = 0; 2 > ax; ++ax) // Look at x axis and y axis
{
for(c0 = 0; 2 > c0; ++c0) // Look at both corners of obj[0]
{
for(c1 = 0; 2 > c1; ++c1) // Look at both corners of obj[1]
{
float dist = fabs(obj[0].corner(c0).coordinate(ax) - obj[1].corner(c1).coordinate(ax));
if (dist < gap)
{
gap = dist;
closest.ax = ax;
closest.c0 = c0;
closest.c1 = c1;
}
}
}
}
int other = 1 - closest.ax; // The other axis
cout << "The closest gap is along the " << (closest.ax ? 'y' : 'x') << " axis\n";
cout << "The common side is along the " << (other ? 'y' : 'x') << " direction\n";
// Make a list of the 4 points along the common side
Vec2D list[4];
list[0] = obj[0].corner(closest.c0);
list[1] = obj[0].along(closest.c0, other);
list[2] = obj[1].corner(closest.c1);
list[3] = obj[1].along(closest.c1, other);
// Sort them into order along the common axis
qsort(list, 4, sizeof(Vec2D), closest.ax ? compare_x : compare_y);
// Get the average of the 2 middle points along the common axis.
Vec2D answer = {
(list[1].x + list[2].x) / 2,
(list[1].y + list[2].y) / 2
};
cout << "(" << answer.x << "," << answer.y << ")\n";
}
I built the following code to read 4 pairs of coordinates to calculate if it's a square or not:
#include <iostream>
using namespace std;
struct {
int x;
int y;
}a[10];
int dist(int x1, int y1, int x2, int y2)
{
// function to compute the (square of the) distance between two points
int c1, c2;
c1 = x2-x1;
c2 = y2-y1;
return (c1*c1)+(c2*c2);
}
int main()
{
int d1, d2, d3, d4;
for (int i=1; i<=4; i++)
{
cout << 'X' << i << '='; cin >> a[i].x;
cout << 'Y' << i << '='; cin >> a[i].y;
}
d1 = dist(a[1].x, a[1].y, a[2].x, a[2].y);
d2 = dist(a[2].x, a[2].y, a[3].x, a[3].y);
d3 = dist(a[3].x, a[3].y, a[4].x, a[4].y);
d4 = dist(a[4].x, a[4].y, a[1].x, a[1].y);
if(d1==d2 && d1==d3 && d1==d4)
cout << "Is a square";
else
cout << "Is not a square";
return 0;
}
The code works well enough, but I want to read multiple coordinates (more than four) and check every possible combination of four points to see if they make a square.
I can't figure out how to extend the method above to work with more than four points as input (and selecting all combination of four from that); can anyone give me a hint/hand please?
This sounds like a complete-graph problem. Since all points are int's, one thing I can think of is doing a depth-first search, without duplicates, with the distance^2 as the weight. And you sorta need a dual-pseudograph to keep the angle info (a boolean suffices for right-angle v.s. non-right-angle).
Start from a point 0 , step to the nearest neighbor 1, and then, start from the neighbor 1, find its neighbors 2,3,4 ..., and filter on two criteria: distance and angle. Each depth-first search needs only 4 steps max, since there are only 4 sides.
Iterate through all points, and book-keeping visited points, you may track how many squares made during the way.
Here is some code that checks all combinations of four points to see if they are square. Note that your original method for testing "square" was faulty - first, even if points were given in the correct order, a diamond shape would (wrongly) be called "square"; second, if points were given in the "wrong" order, a square might not look square.
I fixed both those issues. Also, I created a simple nested loop that generates all possible combinations of four points and tests them; this can be made much more efficient (for example, if points 1,2 and 3 do not form a "isosceles right triangle" there is no point to test the fourth point - so you can save a lot of time by not testing for all other possible points). I will leave that for another time.
I did not bother writing the "input N points" part of the code - I don't think that is what you were struggling with. Let me know if I was wrong to assume that.
#include <iostream>
typedef struct{
int x;
int y;
} point;
int isSquare (point *p1, point *p2, point *p3, point *p4) {
double dx, dy;
double dd[6];
point *pp[4];
pp[0]=p1; pp[1]=p2; pp[2]=p3; pp[3]=p4;
int ii, jj, kk, nn;
kk = 0;
// loop over all combinations of first and second point
// six in all
for(ii=0; ii<3; ii++) {
for(jj=ii+1; jj<4; jj++) {
dx = pp[ii]->x - pp[jj]->x;
dy = pp[ii]->y - pp[jj]->y;
dd[kk]= dx*dx + dy*dy;
if (dd[kk]==0) return 0; // two identical points: not a square
if(kk>1) {
for(nn= 0; nn < kk-1; nn++) {
// if both are "sides", we expect their length to be the same;
// if one is a diagonal and the other a side, their ratio is 2
// since we are working with the square of the number
if (!(((2*dd[nn] == dd[kk] ) || (dd[nn] == dd[kk]) || 2*dd[kk] == dd[nn] ))) return 0;
}
}
kk++;
}
}
return 1; // got here: all combinations tested OK, we have a square
}
int main(void) {
// pick ten numbers - chosen so there are two squares
point p[10]={{1,2},{3,2},{1,4},{7,8},{2,4},{3,4},{6,7},{8,7},{2,5},{3,5}};
double d2[10][10];
int ii, jj, kk, ll;
// loop over all possible combinations:
// since there are just four to pick we can hard-wire the loop
for(ii=0; ii<7; ii++) {
for(jj = ii+1; jj<8; jj++) {
for(kk = jj+1; kk<9; kk++) {
for(ll = kk+1; ll<10; ll++) {
if(isSquare(p+ii, p+jj, p+kk, p+ll)) {
std::cout << "combination: " << ii << "," << jj << "," << kk << "," << ll << " is a square\n";
}
}
}
}
}
}
Output:
combination: 0,1,2,5 is a square
combination: 4,5,8,9 is a square