I have written a simple battleship game in C++. After several iterations of the game, one of the strings in a "Player" object is changed. This change is several null characters are added to the end of the string. Otherwise the rest of the object is untouched. For example if the player type is "cpu", the player type switches to "cpu\0\0\0\0\0\0\0\0". I believe the line of code causing the problem is:
currPlayer->getStrategy().getNextAttack(nextPlayer->getBoard(1));
Here is the code for getNextAttack():
int Strategy::getNextAttack(Board enemyBoard) {
//clear prob board
for(int i = 0; i < 100; i++) {
probBoard[i] = 0;
}
//reset largest ship
largestShip = 0;
//assign largest ship
for(int i = 0; i < 100; i++) {
Ship currShip = enemyBoard.getShipByCoord(i);
if(!currShip.isSunk()) { //if ship is still afloat
if(currShip.getSize() > largestShip) { largestShip = currShip.getSize(); } //reassign largest ship on board
}
}
//assign base prob
std::vector<int> allPossible;
//for all horiz coords
for(int i = 0; i < 10; i++) {
for(int j = 0; j < (10 - largestShip +1); j++) {
for(int k = 0; k < (largestShip); k++) {
if(!enemyBoard.beenHit((i*10) + j + k) || (enemyBoard.beenHit((i*10) + j + k) && !enemyBoard.getShipByCoord((i*10) + j + k).isSunk())) { //if not hit or if hit but contains a ship that is not sunk
allPossible.push_back((i*10) + j + k);
}
else {
for(int m = 0; m < k; m++) {
allPossible.pop_back(); //should delete last element
}
break;
}
}
//for all vert coords
for(int z = 0; z < (largestShip); z++) {
if(!enemyBoard.beenHit(((j+z)*10) + i)) {
allPossible.push_back(((j+z)*10) + i);
}
else {
for(int m = 0; m < z; m++) {
allPossible.pop_back(); //should delete last element
}
break;
}
}
}
}
for(int p = 0; p < allPossible.size(); p++) {
probBoard[allPossible[p]] += 1;
}
//add improvements based on hits
for(int i = 0; i < 10; i++) {
for(int k = 0; k < 10; k++) {
int currCoord = (i*10) + k;
int leftCoord = (i*10) + k-1;
int rightCoord = (i*10) + k+1;
int upCoord = ((i-1)*10) + k;
int downCoord = ((i+1)*10) + k;
if(enemyBoard.beenHit(currCoord) && (enemyBoard.getShipByCoord(currCoord).getName() != "") && !enemyBoard.getShipByCoord(currCoord).isSunk()) { //currCoord is a coordinate that has been hit, contains a ship and is not sunk
if((enemyBoard.beenHit(leftCoord) || enemyBoard.beenHit(rightCoord)) && (enemyBoard.getShipByCoord(leftCoord) == enemyBoard.getShipByCoord(currCoord) || enemyBoard.getShipByCoord(rightCoord) == enemyBoard.getShipByCoord(currCoord))) { //if space to left or right is hit and the same ship
//increment only the left and right
if(!enemyBoard.getShipByCoord(currCoord).isSunk()) { //ship cannot be sunk as well
probBoard[leftCoord] += 25;
probBoard[rightCoord] += 25;
}
}
else if((enemyBoard.beenHit(upCoord) || enemyBoard.beenHit(downCoord)) && (enemyBoard.getShipByCoord(upCoord) == enemyBoard.getShipByCoord(currCoord) || enemyBoard.getShipByCoord(downCoord) == enemyBoard.getShipByCoord(currCoord))) { //if space on top or bottom is hit and the same ship and not sunk
//increment only the top and bottom
if(!enemyBoard.getShipByCoord(currCoord).isSunk()) { //ship cannot be sunk as well
probBoard[upCoord] += 25;
probBoard[downCoord] += 25;
}
}
//if no direct spaces in any direction to hit coord, increment top, bot, left, and right equally
else {
probBoard[upCoord] += 20;
probBoard[downCoord] += 20;
probBoard[leftCoord] += 20;
probBoard[rightCoord] += 20;
}
}
}
}
//marks odds at 0 if already fired upon
for(int n = 0; n < 100; n++) {
if(enemyBoard.beenHit(n)) {
probBoard[n] = 0;
}
}
//find next best attack coord based on prob board
int highestValue = 0;
std::vector<int> highestSpaces;
for(int j = 0; j < 100; j++) {
if(probBoard[j] > highestValue) { highestValue = probBoard[j]; }
}
for(int r = 0; r < 100; r++) {
if(probBoard[r] == highestValue) {
highestSpaces.push_back(r);
}
}
srand(static_cast<unsigned int>(time(NULL)));
int randNum = rand() % highestSpaces.size();
return highestSpaces[randNum];
}
Thank you for reading and any help!
This looks like it will go out of the array bounds at the edges when the row or column is 0 or 9:
probBoard[upCoord] += 20;
probBoard[downCoord] += 20;
probBoard[leftCoord] += 20;
probBoard[rightCoord] += 20;
Related
I'm trying to write a programm to find a maximum value in column in a initialized 5x5 matrix, and change it to -1. I found out the way to do it, but i want to find a better solution.
Input:
double array2d[5][5];
double *ptr;
ptr = array2d[0];
// initializing matrix
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
if (j % 2 != 0) {
array2d[i][j] = (i + 1) - 2.5;
} else {
array2d[i][j] = 2 * (i + 1) + 0.5;
}
}
}
This is my solution for the first column :
// Changing the matrix using pointer arithmetic
for (int i = 0; i < (sizeof(array2d) / sizeof(array2d[0][0])); ++i) {
if (i % 5 == 0) {
if (maxTemp <= *(ptr + i)) {
maxTemp = *(ptr + i);
}
}
}
for (int i = 0; i < (sizeof(array2d) / sizeof(array2d[0][0])); ++i) {
if (i % 5 == 0) {
if (*(ptr + i) == maxTemp) {
*(ptr + i) = -1;
}
}
}
I can repeat this code 5 times, and get the result, but i want a better solution. THX.
Below is the complete program that uses pointer arithmetic. This program replaces all the maximum values in each column of the 2D array -1 as you desire.
#include <iostream>
int main()
{
double array2d[5][5];
double *ptr;
ptr = array2d[0];
// initializing matrix
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
if (j % 2 != 0) {
array2d[i][j] = (i + 1) - 2.5;
} else {
array2d[i][j] = 2 * (i + 1) + 0.5;
}
}
}
//these(from this point on) are the things that i have added.
//Everything above this comment is the same as your code.
double (*rowBegin)[5] = std::begin(array2d);
double (*rowEnd)[5] = std::end(array2d);
while(rowBegin != rowEnd)
{
double *colBegin = std::begin(rowBegin[0]);
double *colEnd = std::end(rowBegin[0]);
double lowestvalue = *colBegin;//for comparing elements
//double *pointerToMaxValue = colBegin;
while(colBegin!= colEnd)
{
if(*colBegin > lowestvalue)
{
lowestvalue = *colBegin;
//pointerToMaxValue = colBegin ;
}
colBegin = colBegin + 1;
}
double *newcolBegin = std::begin(rowBegin[0]);
double *newcolEnd = std::end(rowBegin[0]);
while(newcolBegin!=newcolEnd)
{
if(*newcolBegin == lowestvalue)
{
*newcolBegin = -1;
}
++newcolBegin;
}
++rowBegin;
}
return 0;
}
The program can be checked here.
You can add print out all the element of the array to check whether the above program replaced all the maximum value in each column with -1.
I have written it in java but I think u can understand. This one is for all 5 columns at the same time. You can try this:
int count = 0;
double max = 0;
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
if (j == 0) {
max = array2d[j][I];
count = 0;
}
if (array2d[j][i] > max) {
count = j;
}
}
array2d[count][i] = -1;
}
I am trying to create a simulation of conway's game of life.
I keep getting a "vector subscript out of range" error after about 300 generation and I don't understand the reason. From what I could gather it's caused by using an invalid index. The most likely section is the first part of the draw function where I find empty rows and replace them with "\n" to save time.
I've started learning to code not too long ago so I may be making baby mistakes.
Edit: visual studio point the error after the third for loop in the frame function, on if (emptyRows[m] == i)
Here's the full code :
#include <array>
#include <time.h>
#include <vector>
const int WIDTH = 150;
const int HEIGHT = 50;
bool table[WIDTH][HEIGHT];
bool tableNew[WIDTH][HEIGHT];
std::string buffer;
int total;
int counter = 0;
std::vector<int> emptyRows;
int numberOfNeighbours(int Y, int X) {
if (X == 0 || Y == 0 || X == WIDTH || Y == HEIGHT)
return 2;
total = 0;
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
if (table[X + j][Y + i] == true)
total++;
}
}
total -= table[X][Y];
return total;
}
void draw() {
srand((int)time(0));
int m = 0;
bool check = 0;
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
if (table[j][i] == 1)
check = 1;
}
if (check == 0)
emptyRows.push_back(i);
else
check = 0;
}
for (int i = 0; i < HEIGHT; i++) {
if (emptyRows.size() >= 1) {
if (emptyRows[m] == i) {
buffer.append("\n");
m++;
continue;
}
}
for (int j = 0; j < WIDTH; j++) {
if (table[j][i] == 1) buffer.push_back('#');
else buffer.push_back(' ');
}
buffer.append("\n");
}
std::cout << buffer;
std::cout << std::endl << "Generazione numero:" << counter;
emptyRows.erase(emptyRows.begin(), emptyRows.end());
buffer.erase(buffer.begin(), buffer.end());
m = 0;
}
void reset() {
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
table[j][i] = tableNew[j][i];
}
}
}
void logic() {
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
int k = numberOfNeighbours(i, j);
if (table[j][i] == 0 && k == 3)
tableNew[j][i] = 1;
else if (table[j][i] == 1 && k != 2 && k != 3)
tableNew[j][i] = 0;
else
tableNew[j][i] = table[j][i];
}
}
}
int main(){
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
if ((rand() % 2) == 1)
table[j][i] = 1;
}
}
while (true) {
counter++;
draw();
logic();
reset();
system("cls");
}
return 0;
}
Say that I have a sequence:
int seq[4][4];
Then, lets say seq[1][2]=8;
No other values of the sequence yields 8.
If I want to find the values of a sequence and print out which one it is, (e.g. 1,2 and make x=1 and y=2) how can I do that? What
int x,j;
for (int i = 0; i < 4; i++) // looping through row
{
for(int j = 0; j < 4; j++) //looping through column
{
if (seq[i][j] == 8) //if value matches
{
x = i; y = j; //set value
i = 4; //set i to 4 to exit outer for loop
break; //exit inner for loop
}
}
}
int numberBeingSearchedFor = *Any Value Here*;
int array[*numRows*][*numColumns*];
int firstOccuranceRow = -1, firstOccuranceColumn = -1;
for(int i = 0; i < numRows; ++i)
{
for(int j = 0; j < numColumns; ++j)
{
if(array[i][j] == numberBeingSearchedFor)
{
firstOccuranceRow = i;
firstOccuranceColumn = j;
i = numRows; //Credit to other answer, I've never seen that :) It's cool
break;
}
}
}
if(firstOccuranceRow == -1 || firstOccuranceColumn == -1)
{
//Item was not in the array
}
A randomly generated 4x4 2-D array is given to the user, of which one element is definitely 0. Considering 0 to be an empty location, the user will have to exchange the remaining 15 elements with 0 repeatedly until they get the array in ascending order, with 0 as the last element.
At this point, they're allowed to exchange any element with 0.
But how do I modify this code to ensure that are only able to exchange those elements with 0 that are adjacent to it (either above, below or beside it) ?
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
int check_asc(int a[][4])
{
int i, j, previous = a[0][0];
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
if(i == 3 && j == 3)
{
if (a[i][j] == 0)
return 1;
}
else if (a[i][j] < previous)
{
return 0;
}
previous = a[i][j];
}
}
return 1;
}
void swap(int a[][4], int &xpos, int &ypos)
{
int arr, temp;
cout << "\n\nEnter number to be swapped with 0: ";
cin >> arr;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (a[i][j] == arr)
{
temp = a[xpos][ypos];
a[xpos][ypos] = a[i][j];
a[i][j] = temp;
xpos = i;
ypos = j;
return;
}
}
}
}
int check_rep(int a[][4], int assign)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (assign == a[i][j])
return 0;
}
}
return 1;
}
void main()
{
int a[4][4], assign, xpos = 0, ypos = 0, asc_result, rep_result;
srand((unsigned)time(NULL));
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
if (i == 0 && j == 0)
a[i][j] = 0;
else
{
do {
assign = rand() % 50;
rep_result = check_rep(a, assign);
} while (rep_result == 0);
a[i][j] = assign;
}
}
cout << "\n\nArrange the 4x4 matrix into ascending order. (Consider 0 as a blank space)" << endl;
for (int i = 0; i < 4; i++)
{
cout << endl;
for (int j = 0; j < 4; j++)
cout << a[i][j] << '\t';
}
do {
swap(a, xpos, ypos);
system("cls");
for (int i = 0; i < 4; i++)
{
cout << endl;
for (int j = 0; j < 4; j++)
cout << a[i][j] << '\t';
}
asc_result = check_asc(a);
} while (asc_result == 0);
cout << "\n\tYou win"<<endl;
system("pause");
}
Simple, just extend your swap function with a piece of code that will check whether the location of the element to be swapped is adjacent to the location of 0:
void swap(int a[][4], int &xpos, int &ypos)
{
...
if (a[i][j] == arr &&
((i == xpos && (j == ypos - 1 || j == ypos + 1)) ||
(j == ypos && (i == xpos - 1 || i == xpos + 1))))
{
temp = a[xpos][ypos];
a[xpos][ypos] = a[i][j];
a[i][j] = temp;
xpos = i;
ypos = j;
return;
}
An improvement would be to separate the check condition and inform the user in case when the element is not adjacent to 0.
Rough Algorithm
1) create a function find location, it will return a structure Point that has x, y integer fields, it will find the x, y location of any piece based on the pieces value, i.e. lets say 0 is entered, if it is located in the top left corner (0,0), a point (0, 0) will be returned
2) create a function that takes in 2 points, the location of the '0' and the location of the piece we wish to swap lets call it S, if S.x = 0.x and 0.y - 1 = S.y or S.y - 0.y + 1 then you know that said piece is directly above or below the 0, now of course you have ot add a few conditions for boundaries so as we dont check outside the grid. Have this function return an int 1 if the piece S is located above/below/beside, 0 if not.
3) if 1 is returned your allowed to do the flip, if 0 is returned find another piece
I'm tasked with solving the Knights tour iteratively using a stack to store the previous moves so I can pop if the knight is stuck. My program seems to be making multiple POPS but doesn't seem to be ever solving the puzzle.
It uses Warnsdorffs rule for the first 32 moves and then uses a stack to solve the remaining spaces.
Is there something wrong with my logic so that it never solves the puzzle?
Is this a legal move function
bool safe(int row, int col) {
if (row >= 0 && row < 8 && col >= 0 && col < 8 && arr[row][col] == -1){
return true;
}
return false;
}// end safe
Here is the solve function
void solve(){
int x = 0; // initial start
int y = 0; // initial start
arr[0][0] = 0; // loading array with starting position
int nextMoveX, nextMoveY; // next move
Location top;
top.x = 0;
top.y = 0;
for(int i = 0; i < 8; i++){
top.movesArray[i] = safe(top.x+moveX[i], top.y+moveY[i]);
}
locate.push(top); // loading stack with initial position
int bestMove[8]; // array to sort best move
int counter = 0; // move counter
int count = 0;
while(counter < 63){
top = locate.top(); // check top of stack for current position
x = top.x;
y = top.y;
//loops through the 8 move choices
// using a stack to solve final steps
if( counter >= 31){
for(int i = 0; i < 8; i++){
top = locate.top();
if(top.movesArray[i]){
if(counter == 42){
cout << i;
}
//updates the top of the stack removing the
move just made from being made on a POP
top.movesArray[i] = false;
locate.pop();
locate.push(top);
counter++;
nextMoveX = x + moveX[i];
nextMoveY = y + moveY[i];
arr[nextMoveX][nextMoveY] = counter;
top.x = nextMoveX;
top.y = nextMoveY;
print();
cout << counter;
for(int j = 0; j < 8; j++){
top.movesArray[j] = safe(nextMoveX+moveX[j], nextMoveY+moveY[j]);
cout << top.movesArray[j];
}
locate.push(top);
break;
}
//if no more valid moves from this space pop off
if(i == 7){
arr[top.x][top.y]= -1;
locate.pop();
counter --;
cout << "pop";
top = locate.top();
for(int a = 0; a < 8; a++){
cout << top.movesArray[a];
}
break;
}
}
}
// heuristics for first 32 moves
else{
for(int i = 0; i < 8; i++){
bestMove[i] = -1; // resets # of potential moves at next space
print();
// test next position
nextMoveX = x + moveX[i];
nextMoveY = y + moveY[i];
//if safe count number of moves on next space
if(safe(nextMoveX,nextMoveY)){
for( int j = 0; j < 8; j++){
if(safe(nextMoveX+moveX[j],nextMoveY+moveY[j])){
bestMove[i] += 1;
}
}
}
//if on last move check for one with least moves available
if(i ==7){
int least = 8;
int pos = -1;
int L;
for(L = 0; L < 8; L++){
if(bestMove[L] < least && bestMove[L] != -1 && bestMove[L]!= 0){
least = bestMove[L];
pos = L;
}
} // end for
counter++;
nextMoveX = x + moveX[pos];
nextMoveY = y + moveY[pos];
arr[nextMoveX][nextMoveY] = counter;
top.x = nextMoveX;
top.y = nextMoveY;
for(int e = 0; e < 8; e++){
top.movesArray[e] = safe(nextMoveX + moveX[e],nextMoveY + moveY[e]);
}
locate.push(top);
} // end if (i=7)
} // end for i
} // end else
} // end while
} // end solve
It is probably a SIGSEGV (segmentation fault) because you are trying to write past the size of arr.
How is arr declared? Do you make sure that when you do this:
arr[nextMoveX][nextMoveY] = counter;
nextMoveX and nextMoveY are within the array dimension values as declared(or malloc'd)?