I'd like to make non-graphic (text) C++ game (you move your character using n, s, w, e and every location is described). Locations will be an array of an objects (there will be location description and other information in this array). I've started making this game, but I have a question: Is it possible to make arrays with dimensions x - from -100 to 100 and z - from -100 to 100? If it is not possible, are there other ways to do it? (I don't want a [0][0] position in one of 4 corners, but on the middle.)
An Array can have only positive indexes:
Location loc[201][201];
define a Funktion that returns your desired Location:
Location getLocation(int xCoord, int yCoord)
{
if (abs(x)>100 || abs(y)>100)
throw std::invalid_argument( "value out of range");
return loc[xCoord+100][yCoord+100];
}
Then you can get the Location by calling the function getLocation(x,y)
One common (but rather sketchy) method is to do something like this (example for 21 x 21 board):
#include <iostream>
using namespace std;
int main()
{
typedef int (*board_ptr)[21];
int board_data[21][21];
board_ptr board = (board_ptr)&board_data[10][10];
for (int i = -10; i <= 10; ++i)
for (int j = -10; j <= 10; ++j)
board[i][j] = 0;
board[-10][-10] = 1;
board[-10][10] = 2;
board[10][-10] = 3;
board[10][10] = 4;
board[0][0] = 5;
for (int i = -10; i <= 10; ++i)
{
for (int j = -10; j <= 10; ++j)
{
cout << " " << board[i][j];
}
cout << endl;
}
return 0;
}
This creates a normal 21x21 array but then it also creates a pointer to a fake array which is initialised to point at the centre of the real array. You can then use this fake pointer as if it were a real array with indices ranging from -10 to +10 (inclusive).
LIVE DEMO
Related
Just started using cLion as an ide for c++. Am attempting to run this block of code where it reads a csv file and stores the values in a 189 x 141 2d vector. It then iterates through 5 for loops. Everything was running smoothly until I included the 5 nested for loops; at this point I was seeing the "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)" message upon executing. I have seen an answer to a similar question claiming that it is the result of a lack of memory on my computer. Would this be the case?
When the first 3 for loops have ib0, ib1, ib2 iterate from 0 to 100, it would of course mean that there are over 26 billion iterations in total. However, when I reduce this range to 0 to 1, I still receive the message.
For reproducibility, I just have the ROB vector be 189 x 141 random values.
EDIT: If anyone runs this code, let me know how long it takes?
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
double innerarrayval;
vector<vector<double>> ROB;
vector<double> innerarray;
for(int x=0;x<189;x++) {
innerarray.clear();
for (int y = 0; y < 141; y++) {
innerarrayval = rand() % 1000;
innerarray.push_back(innerarrayval);
}
ROB.push_back(innerarray);
}
double b0,b1,b2;
int nnb;
double chisquared, amean, content, sumpart, sumpartsquared,chisquaredNDOF,chimin;
double b0mem, b1mem, b2mem;
chimin = 1000.0;
for(int ib0 = 0; ib0 < 101; ib0++)
{
b0 = 15.0 + 0.1 * (ib0 - 1);
for(int ib1 = 0; ib1 < 101; ib1++)
{
b1 = -0.002 * (ib1 - 1);
for(int ib2 = 0; ib2 < 101; ib2++)
{
b2 = 0.002 * (ib2 - 1);
nnb = 0;
chisquared = 0;
amean = 0;
for(int i = 0; i <= 189; i++)
{
for(int j = 0; j <= 141; j++)
{
if((i >= 50 and i <= 116) and (j >= 42 and j <= 112))
{
continue;
}
else
{
content = ROB[i][j];
if(content == 0)
{
content = 1;
}
amean = amean + content;
sumpart = (content - b0 - (b1 * i) - (b2 * j))/sqrt(content);
sumpartsquared = pow(sumpart, 2);
chisquared = chisquared + sumpartsquared;
nnb = nnb + 1;
}
}
}
chisquaredNDOF = chisquared/double(nnb);
amean = amean/double(nnb);
if(chisquaredNDOF < chimin)
{
chimin = chisquaredNDOF;
b0mem = b0;
b1mem = b1;
b2mem = b2;
}
}
}
}
cout<<"chi squared: "<<chimin<<"\n";
cout<<"b0: "<<b0mem<<"\n";
cout<<"b1: "<<b1mem<<"\n";
cout<<"b2: "<<b2mem<<"\n";
cout<<"mean: "<<amean<<"\n";
return 0;
}
for(int x=0;x<189;x++) {
innerarray.clear();
for (int y = 0; y < 141; y++) {
innerarrayval = rand() % 1000;
innerarray.push_back(innerarrayval);
}
ROB.push_back(innerarray);
}
This part of the initialization loops carefully, and gingerly, initialized the two-dimensional ROB vector. As noted by each for loop's limit, the valid indexes for the first dimension is 0-188, and the 2nd dimension is 0-140.
This is correct. In C++ array/vector indexes start with 0, so for your expected result of a "189 x 141 2d vector", the first index's values range 0-188, and the 2nd one's range is 0-140.
If you proceed further in your code, to the part that reads the two-dimensional matrix:
for(int i = 0; i <= 189; i++)
{
for(int j = 0; j <= 141; j++)
{
And because this uses <=, this will attempt to access values in ROB whose first dimension's index range is 0-189 and the 2nd dimension's index range is 0-141.
The out of bounds access results in undefined behavior, and your likely crash.
You should use this obvious bug as an excellent opportunity for you to learn how to use your debugger. If you used your debugger to run this program, the debugger would've stopped at the point of the crash. If you then used your debugger to inspect the values of all variables, I would expect that the out-of-range values for i or j would be very visible, making the bug clear.
if I have the array N[12] and I have the code:
float N[12];
for (int X = 1; X < 12; X++) {
N[X] = N[X] + 2;
cout << N[X] << endl;
}
what else do I need to get this to display odd numbers starting at 1 and increasing until I have 12?? (so until 23)
Its outputting a really weird slew of numbers
I'm pretty new to c++, I know this is a silly question, sorry...
Your array is not initialized to any values, so depending on how your compiler does it, it most likely will be filled with random values. This would explain why you are seeing weird numbers.
Since you want to start with a initial value of 1, you can initialize your array like this:
float N[12] = { 1 };
This will set the first element of the array to 1 and the rest of the elements will be set to 0. But then the other person is right, in that you want to add 2 to the previous element in your array. So it would make the code into this:
float N[12] = { 1 }
int X;
for(X=1; X<12; X++){
N[X]= N[X-1] + 2;
cout << N[X] << endl;
}
Couple of issues in your code as mentioned below.
Major issue : your array is uninitialized. So when you perform N[x] = N[x] + 2, it is meaningless as N[x] doesn't have any value.
Minor issue : No need to declare array as float as we are going to store integer values.
Below is the code.
#include <iostream>
using namespace std;
int main()
{
int N[12];
for(int x = 0; x < 12; x++)
{
N[x] = (2 * x) + 1;
cout << N[X] << endl;
}
return 0;
}
I think you mean to add two to the previous element, not the current one, since the current one is uninitialized. Also, since odd numbers are integers, you don't need floats.
int n[12];
n[0] = 1; // start off with the first odd
for (int x = 0; x < 12; x ++) {
// we already have a value for n[0] so we shouldn't overwrite it
if (x != 0) {
// n[x - 1] gets the previous value
n[x] = n[x - 1] + 2;
}
std::cout << n[x] << std::endl;
}
I'm writing a battleship game in the console, and I'm writing a function that will draw one grid based on a 2-dimensional array. The approach I'm taking is such:
--> Draw 1 row which contains a character X amount of times (like 10)
--> Draw that row, putting a newline at the end of the drawing process, 10 times to get a nice field.
Now, I do need to insert a newline at the end of 1 row, right? But how do I compare only the x-element of the array, and not the y-element?
Here's my code:
// Includes
#include <iostream> // For IO
#include <cstdlib> // For rand()
// Important game stuff
const int empty = 0; // Water
const int occupied = 1; // Ship
const int hit = 2; // Hit a ship
const int missed = 3; // Missed
// Variables
const int fields = 10;
// We want a 10x10 field
int board[fields][fields]; // board[x][y]
// Initialize board
void initb(int array[fields][fields]);
// Draw board x-axis
void drawbx(int array[fields][fields]);
int main(void)
{
drawbx(board;)
// game(Players);
return 0;
}
// Initialize the board, make everything hit
void initb(int array[fields][fields])
{
for(int x = 1; x <= 10; x++)
{
for(int y = 1; y <= 10; y++)
{
array[x][y] = hit;
}
}
}
void drawbx(int array[fields][fields])
{
for(int i = 1; i <= fields; i++)
{
if(array[i][] == empty || array[i][] == occupied)
{
if(i == 10)
std::cout << " X\n";
else if(i == 1)
std::cout << "X ";
else
std::cout << " X ";
}
}
}
Take a look specifically at the drawbx() function. I want to draw something like
X X X X X X X X X X\n
The syntax that I tried, if(array[i][] == empty || array[i][] == occupied), doesn't work. There must be an expression in the second pair of square brackets. Can someone help me?
I see two major problems:
1) Array indexing is out of range. You use index 1 to 10. It shall be 0 to 9.
2) Code array[i][] == empty is illegal syntax. You can't leave one index empty.
If you want a function that draw one row, perhaps pass the row number to the function like:
void draw_one_row(int array[fields][fields], int row_to_draw)
{
for(int i = 0; i < fields; i++)
{
if(array[row_to_draw][i] == empty || array[row_to_draw][i] == occupied)
{
...
}
}
}
To draw the whole board:
void draw_board(int array[fields][fields])
{
for(int i = 0; i < fields; i++)
{
draw_one_row(array, i);
}
}
BTW: Since you write C++, I'll recommend that you use vector instead of arrays.
I am using an arduino to read a sensor which stores 256 values into an array. I am trying to find local max's but some values being stored have repeating values to the left and right of itself causing the value to print multiple times. Is there a way to take all true values meaning they are a max value and store them in another array to process and reduce the repeated values to just 1 value...
OR is there a way to send the max values to another array where the repeated values get reduced to just 1? OR
IE:
Array1[] = {1,2,3,4,4,4,3,2,7,8,9,10}
max = 4 at index 3
max = 4 at index 4
max = 4 at index 5
since 4 is a peak point but repeats how can I reduce it so that the array looks like
Array2[] = {1,2,3,4,3,2,7,8,9,10}
max = 4 at index 3
I need the most basic breakdown if possible nothing on an expert level, thanks.
Code from Arduino:
int inp[20] = {24,100,13,155,154,157,156,140,14,175,158,102,169,160,190,100,200,164,143,20};
void setup()
{
Serial.begin(9600); // for debugging
}
void loop()
{
int i;
int count = 0;
for (i = 0; i < 20; i++)
{
Serial.println((String)inp[i]+" index at - "+i);
delay(100);
};
int N = 5; // loc max neighborhood size
for (int i = N-1; i < 19-N; i++)
{
bool loc = false;
for (int j = 1; j < N; j++) // look N-1 back and N-1 ahead
{
if (inp[i] > inp[i-j] && inp[i] > inp[i+j]) loc = true;
}
if (loc == true)
{
Serial.println((String)"max = "inp[i]+" at index "+i);
}
}
Serial.println("----------------------------------");
}
You can detect "local maxima" or peaks in a single loop without the need of copying something into another array. You just have to ignore repeating values, and you just have to keep track if the values considered are currently increasing or decreasing. Each value after which this status switches from increasing to decreasing is then a peak:
int main() {
int Array1[] = {1,2,3,4,4,4,3,2,7,8,9,10};
int prevVal = INT_MIN;
enum {
Ascending,
Descending
} direction = Ascending;
for (int i=0; i<sizeof(Array1)/sizeof(*Array1); i++) {
int curVal = Array1[i];
if (prevVal < curVal) { // (still) ascending?
direction = Ascending;
}
else if (prevVal > curVal) { // (still) descending?
if (direction != Descending) { // starts descending?
cout << "peak at index " << i-1 << ": " << prevVal << endl;
direction = Descending;
}
}
// prevVal == curVal is simply ignored...
prevVal = curVal;
}
}
I know there are multiple topic regarding Project Euler #8. But I am using a different approach, no STL.
#include <iostream>
using namespace std;
int main(){
char str[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int size = strlen(str);
int number = 1;
int max = 0;
int product = 0;
int lowerBound = 0;
int upperBound = 4;
for (int i = 0; i <= size/5; i++)
{
for (int j = lowerBound; j <= upperBound; j++)
{
number = number * str[j];
}
product = number;
number = 1;
lowerBound += 5;
upperBound += 5;
if (product > max)
{
max = product;
}
}
cout << "the largest product: " << max << endl;
return 0;
}
the answer is : 550386080, which is way too big and incorrect.
Please tell me what's wrong with my code. No advanced pointers or template technique, just control flow statement and some basic stuff.
Part of your problem is the expression
number = number * str[j];
The str[j] is an ASCII character and you are incorrectly assuming it's a numeric value in the range 0..9. A cheap way to convert a single numeric character to a number would be to say
number = number * (str[j] - '0');
That gets you closer to the correct answer but there is another problem. You are testing each index range like [0..4], [5..9], [10..14], [15..19], etc. You should instead be testing indices [0..4], [1..5], [2..6], [3..7], etc. I'll leave that for you to correct.