Placing a piece in a connect four game using c++ - c++

Ok so i have a homework assignment and i dont know where to start with this function.
bool placePiece(char** pBoard, int colSize, int rowSize, int columnSelection, char player)
The function is to place a piece represented by char player, on the game board char** pBoard (a 2dArray made from colSize and rowSize) the function is to put the players piece at the bottom of the column selected during that players turn. also if a piece is already at the bottom of the column it puts the piece on top of that one and if the column is full it will return false.
really the biggest issue im having is i really dont understand how im supposed to be using pBoard.
Im not looking for someone to do it for me but just to help me start out on the right path.

To solve this, you need to understand arrays and loops. The first argument in your signature is an array containing your board data (and the next two arguments the dimensions of it) - there you need to access the first element at the columnSelection position and set it to the value of the player argument. The return value should indicate if the operation was successful.
bool placePiece(char** pBoard, int colSize, int rowSize, int columnSelection, char player) {
if (columnSelection >= colSize) {
/* invalid column */
return false;
}
for (size_t i = 0; i < rowSize; ++i) {
/* loop to go over all rows - starting with 0 */
if (pBoard[columnSelection][i] == 0) {
/* find first empty row and set it to 'player' value */
pBoard[columnSelection][i] = player;
return true;
}
}
/* no free row found -> all rows already set*/
return false;
}
This code assumes an column-row order in your array and goes from row 0 upwards, but you should get the general idea.

Related

C++ Read Access Violation error was thrown, but I'm not sure why. Tile Slider Puzzle Game

So I'm coding an object oriented Tile Slider Puzzle game, and I feel as though I've coded things correctly, and when I build the project, no errors are thrown. However, when I go to run my code (Visual Studio 2015 IDE) I get a message box saying the .exe file has stopped working. Here are my files thus far:
The following is the TileSlider.h file:
#ifndef TILESLIDER_H
#define TILESLIDER_H
#include <Windows.h>
class TileSlider
{
private:
char** solvedBoard;
char** gameBoard;
//mutator(s)
void setUpBoards(); //keep or copy code to constructor
//other member functions
void printBoard(const HANDLE &consoleOut) const;
void scrambleBoard();
bool isBoardSolved() const;
void makeMove(int move);
public:
TileSlider(); //allocate mem here? maybe call setUpBoards()
~TileSlider(); //deallocate mem here
void playGame();
};
#endif
The following is the TileSlider.cpp file:
#include "TileSlider.h"
using namespace std;
#define SIZE 3 //num of rows and cols to board
// --------------------------------------
// Private Members
// --------------------------------------
// Mutator(s)
void TileSlider::setUpBoards() {
//allocate memory for boards
char** solvedBoard = new char*[SIZE];
char** gameBoard = new char*[SIZE];
for (int i = 0; i < SIZE; i++) {
solvedBoard[i] = new char[SIZE];
gameBoard[i] = new char[SIZE];
}
//fill the boards
char i = 49; // ASCII code for '1'
for (int row = 0; row < SIZE; row++) {
for (int column = 0; column < SIZE; column++) {
gameBoard[row][column] = i;
solvedBoard[row][column] = i;
i++;
}
}
gameBoard[SIZE - 1][SIZE - 1] = 42; // ASCII for '*'
solvedBoard[SIZE - 1][SIZE - 1] = 42;
}
The following is the driver file for my code (TileSliderGame.cpp):
#include "TileSlider.h"
using namespace std;
int main() {
TileSlider* game = new TileSlider();
game->playGame();
delete game;
return 0;
}
To attempt to determine the issue that was occurring, I put a break point to step into where I'm calling playGame() in the driver file (TileSliderGame.cpp). I stepped into that function, and then stepped into where playGame() calls the printBoard(consoleOut) function and I received a Read Access Violation error when I got to this line:
// Other Private Member Functions
void TileSlider::printBoard(const HANDLE &consoleOut) const {
for (int row = 0; row < SIZE; row++) {
for (int column = 0; column < SIZE; column++) {
if (gameBoard[row][column] == 42) { //ASCII code 42 is '*' asterisk
. . .
(The error was thrown at the last line shown above)
Error message:
Exception thrown: read access violation.
this->gameBoard was 0x1110112.
Now, I'm really not sure why I would get a read access violation error within the printBoard() function because it's a private function, and therefore should be able to directly access the private gameBoard variable inside the class. I even tried to see if it would make a difference to create an accessor for the gameBoard, but it didn't (the same error was thrown).
Another note I'd like to make, I started this code in a separate project with an Imperative program design and have got it running as I intend it to. Therefore, I know that the code within my object oriented program regarding how the TileSlider game works is working perfectly fine. I'm just not sure what I may have done wrong when I redesigned the code into an object oriented design.
If what my game is supposed to look like is confusing, the TileSlider gameBoard is a 3x3 2D character array that displays onto the screen like so :
1 2 3
4 5 6
7 8 *
Above is how the gameBoard starts, it is then scrambled and the user then moves the tiles with the "wasd" keys to attempt to win the game. Any tiles moved into their correct position (the positions showed above) are colored green, and any tiles that aren't in their correct position are colored red. The one exception is that the empty tile (the asterisk) is printed in white all of the time.
I don't think that my code is perfect so I'll take any constructive criticism on my code and code design that I can get.
Edit: I removed a large portion of my TileSlider.cpp file code shown above because it was irrelevant to the error I made in my code.
You wrote:
char** solvedBoard = new char*[SIZE];
char** gameBoard = new char*[SIZE];
You probably meant:
solvedBoard = new char*[SIZE];
gameBoard = new char*[SIZE];
The reason is that your declaration of solvedBoard and gameBoard in TileSlider::setUpBoards() effectively hides the TileSlider member variables with the same names, and nothing is assigned to the latter.

Inserting an object from a derived class into another instance of said object (using the vector.insert function) C++

I am currently working through code which has a Road class. This has a vector of lanes and includes a lane class. The lane class has a vector of vehicles and each vehicle has its derived classes (Car, Motorcycle, Lorry).
I would like a vehicle to be able to assess whether it can move into another lane, i.e. be inserted into another lane's vector of vehicles, safely (a car requires some safe distance, so I have already implemented how a vehicle knows if it is clear to switch lanes).
void Road::Simulate(double time)
{
for (unsigned int iLane = 0; iLane < getNLanes()-1; iLane++)
{
for (unsigned int iV = 0; iV < getCurrentLane(iLane)->getNVehiclesinLane(); iV++)
{
std::cout<< " AllowedOvertake TEST "<< getCurrentLane(iLane+1)->allowedOvertake(getCurrentLane(iLane)->getCurrentVehicle(iV)->getPosition(), getCurrentLane(iLane)->getCurrentVehicle(iV)->getMinDistance())<<std::endl;
getCurrentLane(iLane+1)->setCanOvertake(allowedOvertake(getCurrentLane(iLane)->getCurrentVehicle(iV)->getPosition(), getCurrentLane(iLane)->getCurrentVehicle(iV)->getMinDistance()));
if (getCurrentLane(iLane+1)->getCanOvertake() == true)
{
getCurrentLane(iLane+1)->insertVehicle(getCurrentLane(iLane)->getCurrentVehicle(iV), 0);
delete getCurrentLane(iLane)->getCurrentVehicle(iV);
}
}
}
for (unsigned int iLane = 0; iLane < getNLanes(); iLane++)
{
getCurrentLane(iLane)->Simulate(time);
}
}
I loop over all the present lanes, except the last one as any vehicle in this lane cannot overtake. After looping over the vehicles contained in each lane, I have a function which returns a Boolean which confirms whether an overtake scenario can be executed. This is done in allowedOvertake(). If this returns true, I implement an insert function.
My issue/question: How can I make this ideology work, and whether it is sensible to have these setCanOvertake() and getCanOvertake() functions.
One possible solution could be to just pushback a new vehicle into the intended lane, but with the appropriate positions, velocities etc. However, I am not sure how to ensure that the vehicle being entered has the same type (Car, Lorry...) too.
Currently, I do not get any build errors if I exclude the insertVehicle() function, and I have vehicle motion being drawn using QPainter. However, with the insertVehicle() function, I do not get any build errors but I do get a crash once I run the project.
Any help would be appreciated, and apologies for any coding errors (I'm a keen, but very inexperienced C++ user).
For reference, I have the above functions' definitions as follows
bool Lane::allowedOvertake(double pos, double mindist)
{
for (unsigned int iV = 0; iV < getNVehiclesinLane() - 1; iV++)
{
if ((fVehicles[iV]->getPosition() > pos - mindist)// If inside rear safety distance.
|| fVehicles[iV]->getPosition() < pos + mindist)// If inside front safety distance.
{}//continue
else {return false;}
}
return true;
}
//IN Lane.h
bool getCanOvertake() const{return FREE_LANE_OVERTAKE;}
//IN Lane.h
void setCanOvertake(bool overtake = true){FREE_LANE_OVERTAKE = overtake;}
Apologies, I was under the impression I had referenced my insertVehicle() function definition.
void Lane::insertVehicle(Vehicle*v, int ielement) {
Vehicle* vins = new Vehicle(v->getPosition(), v->getVelocity(), v->getAcceleration());
for (unsigned int iDist = 0; iDist < fVehicles.size()+1; iDist++){fVehicles.insert(fVehicles.begin() + (ielement+1), vins);}
}

Passing into a function a part of my matrix (2d array)

In my program im trying to add the values of a sub-part of my 2d array, a small box of 3 by 3 from a 9 by 9 matrix. Im choosing that small box by the % of rows and columns by 3(modulus 3). (meaning it will take cells like [0][0], [0][3], and so on )
which i want those to be my top right corner of the box and then add 2 more rows and columns making it for instance if we started at [0][0] we will add [0-2][0-2] (3 by 3 box). Im calculating that through a function (as a practice to use functions). The problem is that the program seems to only take in the value of the first cell from that small box, and when i try to loop on the rest of that small box, and add their values, it doesnt take the values correctly (or at all)
i want to know if my parameters are wrong, or im giving the function wrong parameters.
any help would be appreciated.
//------------including section-----------
#include <iostream>
#include <cstdlib>
//------------using section---------------
using std::cin;
using std::cout;
using std::endl;
//-----our constants and variables---------
const int N=3; //initializing our rows and cols as constants
int counter=0, arr[N*N][N*N];
int sumofrow=0, sumofcol=0,sumsquare=0;
//-------prototypes----------------
void READ_MATRIX(int arr[][N*N]);
bool issquare(int arr[][N*N],int row, int col);
//-------main-------------
int main()
{
//calling on the function to input our matrix
READ_MATRIX(arr);
//checking what functions returned
if(counter==0)
cout<<1;
else
cout <<0;
return EXIT_SUCCESS;
}
//-----functions--------
//----readmatrix------
void READ_MATRIX(int arr[][N*N])
{
for (int row=0; row<N*N; row++)
for (int col=0; col<N*N; col++) {
cin >> arr[row][col];
if (row%3==0&&col%3==0)
issquare(arr, row, col);
}
}
//---------issquare-------------
bool issquare(int arr[][N*N],int row, int col)
{
sumsquare=0;
for (int r=0;r<3;r++) //trying to loop on values of array
for (int c=0;c<3;c++)//trying to loop {
//r+row(because row is passed into the function at 0,3,6)
//same for col.
sumsquare+=arr[r+row][c+col]; // this is where it goes wrong
}
//checking to see if sum reached a certain value..
if (sumsquare==45)
return true;
else {
counter++;
return false;
}
}
You are adding values before you accept them. For example, when row = 0 and col = 0 in function READ_MATRIX(), you call issquare() before all values under that 3x3 box are accepted. In case you have initialized all values to zero, the only value contributing to your sum is the first value i.e. arr[0][0].
What you need to do is trigger issquare() function for row = 2,4,8 and col = 2,4,8. Inside the function issquare(), index the array as arr[row-r][col-c].
The error is that issquare() is called before the values it uses have been assigned/read. At the call to issquare(), of all values used in that function, only arr[row][col] is known yet.
What you have to do is to first read the data completely, and only then look at their properties.
Your function issquared is getting called on the first element of your array.
>>> 0 % 3
0
So you are trying to access values outside of your array. CLARIFICATION: They are not initialised yet so they do not belong to your array just yet (this is an over-simplification, the issue is related to memory allocation which I don't know if you have started yet)
Change the line:
if (row%3==0&&col%3==0)
To:
if ((row != 0 && col != 0) && (row%3 == 0 && col%3 == 0))
Also I'd suggested doing a similar check for the last element just to make sure your smaller box is within the boundaries of your matrix.

knights tour in c++ using recursion

I have created a class Board which deals with 2d vectors specifically for this purpose. I am trying to solve the Knight's Tour. I want to print out the thing when it is done. Using the recursive voyagingKnight() function I find that it does not do anything, does not print the result. It seems that I would want to increment the step number for the recursive call but this is not working.
The vector argument incs is a 2d vector of increments for moving the knight, in each row a row move in the first colum and a column move in the second column.
Does anyone have any suggestions as to a flaw in my reasoning here?
The relevant code
bool voyaging_knight( Board &board, int i, int j, int steps ,vector< vector<int> > &increments)
{
if( !newplace(theboard, i, j) ) return false;
board.setval(i,j,step);
if( gone_everywhere( board, steps) )
{
cout <<"DONE" << endl;
board.showgrid();
return true;
}
int n;
int in, jn;
for(n=0; n<8; n++ )
{
in = i + increments[n][0];
jn = j + increments[n][1];
if( inboard(board, i, j)&& newplace(board,i,j) )
{
voyaging_knight( board, in, jn, steps+1 ,increments);
return true;
}
}
theboard.setval(i,j,-1);
}
Yes, change this:
voyagingKnight( theboard, inext, jnext, step+1 ,incs);
return true;
To this:
return voyagingKnight( theboard, inext, jnext, step+1 ,incs);
In addition, it seems that you need to return something (probably false) at the end of the function.
BTW, I'm assuming that you have all the entries in theboard initialized to -1.
I'm guessing that you want 1 continuous path made by horse movements on a (chess)-board found by backtracking. In that case you have to pass the board by value, so each path you take has its own instance to fill. By passing by reference, every path fills the same board, so you can never take all the steps.
Also you should pass a result by value and fill it with the positions you visited and return that from the recursive function, so each path has its own instance of resulting positions and by returning it, you end up with the final result.
You should not pass inc because that is just a helper container that doesn't change.
Make the board a global variable, and build up a sequence of visited squares in a global variable too. Make sure that when retracting each tentative step you undo any changes (square visited, last step of sequence). Call your knight's tour function, make it return success if it reaches the end, and do any output after finishing.
Package the whole shebang in a file or as a class, so as to not expose private details to prying eyes.

C++/QT - File reading stops unexpectedly. Everything else is working as it should

I have a very strange issue. I have this code, which is supposed to loop until the end of the file. But it only loops exactly two times. It never finishes the while, but it reaches the end of the "if" or "else" sentence (depending on the file content).
Everything else is working "good", the numbers that are supposed to be going in are going in, and everything seems to be working until it doesn't reach the end of the while.
This is a futoshiki game. The code is supposed to read each line, treat it as a string, and then break it down into chars, which in turn are casted into integers (except for one char, being a less-than or greater-than sign), which make up the position of the cells or the positions between the signs. Then it uses that data to either add a new cell to the board or a new sign between cells.
The first line of a file is the size of the board.
This issue happens with several different files of different sizes, always on the second iteration. I'm running Linux by the way if it makes any difference.
int MainWindow::charToInt(char letter)
{
int number = letter;
return number - 48;
}
void MainWindow::locateInBoard(string data, board gameboard)
{
if (data.size()==3){
int number = charToInt(data[2]);
pair<int,int> coordinate(charToInt(data[0]), charToInt(data[1]));
gameboard.addCell(number,true,coordinate);
}
else{
pair<int,int> firstCoordinate(charToInt(data[0]), charToInt(data[1]));
pair<int,int> secondCoordinate(charToInt(data[2]), charToInt(data[3]));
gameboard.addSign(firstCoordinate, secondCoordinate, data[4]);
}
}
void MainWindow::getBoardFromFile(QString newString, board* ptToBoard)
/*
Each board has a file. The name of the file is determined by the size of the
board to play, the difficulty and the number of board. The text file contains the
sign and numbers of the board. Let's say the number 3 is in position (2,1), then the
file should contain a line "213". For signs, if there is a > between (3,3) and (3,4),
the file should have a line "3334>"
*/
{
QFile file(newString);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
return;
}
QTextStream in(&file);
QString line = in.readLine();
size = line.toInt();
board gameboard(size);
string stdline;
while (!in.atEnd()) {
line = in.readLine();
stdline = line.toStdString();
locateInBoard(stdline,gameboard);
}
*ptToBoard = gameboard;
}
And this is the relevant code of "board".
board::board(int n)
{
boardSize = n;
gameboard = new cell*[boardSize];
for (int i = 0; i<boardSize; i++){
gameboard [i] = new cell[boardSize];
}
pair<int,int> newPosition;
for (int i = 0; i<boardSize; i++){
newPosition.first = i;
for (int j = 0; j<boardSize; j++){
newPosition.second = j;
gameboard[i][j].setPosition(newPosition);
}
}
}
void board::addCell(int number, bool fixed, pair<int,int> position)
{
cell newCell(number,fixed,position);
gameboard[position.first][position.second] = newCell;
}
void board::addSign(pair<int,int> firstPosition, pair<int,int> secondPosition, char sign)
{
cell firstCell = gameboard[firstPosition.first][firstPosition.second];
cell secondCell = gameboard[secondPosition.first][secondPosition.second];
gameRules.setUnequality(firstCell,secondCell,sign);
}
I know it's not pretty, but I should've handed this in Wednesday and it's three am Thursday and I really don't care anymore if it's pretty or hard-coded as long as it's working.
Thanks a lot for your help, I'm really desperate here.
Take a look at the signature of your locateInBoard method:
void MainWindow::locateInBoard(string data, board gameboard)
That's passing the board by value. So all changes made to the board in locateInBoard are applied to a local copy, which will just get thrown away when the function completes.
Try pass-by-reference instead:
void MainWindow::locateInBoard(string data, board & gameboard)
In addition, I'm worried about this:
board gameboard(size); // created locally
// ... lots of processing ...
*ptToBoard = gameboard; // copy using assignment operator
This is something that can work, but you have to make sure your board class correctly supports copying data. C++ generates default assignment operators if you don't write your own, but they don't work for anything other than trivial structures. You'll likely need to implement your own assignment operator or change your code to avoid using assignment or a copy constructor.
Here's a quick alternative that avoids needing to figure out how to write your own operator=:
board * MainWindow::getBoardFromFile(QString newString)
{
// ...
board * gameboard = new board(size);
// ... do all of your stuff ...
// you'll need to change your existing code to use -> instead of .
// if you get an error, return 0 or throw an exception
return gameboard;
}
(If you don't want to support copy constructors and operator=, it's good practice to write your own anyway — just make them do nothing and markthem private in your header. This'll allow the compiler to help you catch unintended copying.)