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.
Related
I need to make a code that checks if parameter r is a winner.
int is_winner(const float r){
}
You could try something like the following.
if (r <= max_winner && r => 0) {
if (/* simple criterion */) { // i.e. whole game even
return true;
} else if ( /* recursive call */ ){ // recursion, i.e. r/2 is winner and r*r is winner
return true;
}
}
Note that I assume (for sake of simplicity) that the output of your function should be a boolean variable, since the function is called is_winner, where we just want to check if it is true or false.
Try to fill in the conditions on your own. Note, that there are functions like std::floor, std::ceil. Also be aware of conversion from float or double to integer; e.g. check the beahviour of
float r = 2.7189;
int r_int = r;
(I'm not giving code because I think this is an exercise that you should make yourself)
In this particular exercise, it is harder to understand what the required test actually is than to implement it after a lesson on recursive functions.
Basically, if the number is within the range and the integer part of the number is not even, check its half and its square until one of them goes out of limit or is even by calling is_winner() for both from within is_winner() and pass the result back (both should be winners) until you know that the given number is a winner or not.
I would print results in the function to see what is going on.
I guess, since 0 is part of the range, half is always a winner if the number is within the range.
I already have tried to modify my algorithm to work better, but I haven't achieved any result. My problem is that after the first moves, if I have, for example:
XX.
OO.
...
The Computer, instead of choosing 0 2, choses for example 1 2 and sometimes tries to go for position it can't.
My code:
#include "game.hpp"
pair<int,int> winner;
int m = INT_MAX;
pair<int,int> game::minimax(State ini) {
int v = maxValue(ini);
cout << v << endl;
return winner;
}
int game::maxValue(State u){
int check = u.getUtility();
if( check % 700 == 0 ) {
if( u.moves < m ) {
winner = u.move;
m = u.moves;
}
return check;
}
int v = INT_MIN;
u.makeDescendents();
while( !u.ls.empty() ) {
v = max(v,minValue(u.ls.front()));
u.ls.pop_front();
}
return v;
}
int game::minValue(State u) {
int check = u.getUtility();
if( check % 700 == 0 )
return check;
int v = INT_MAX;
u.makeDescendents();
while( !u.ls.empty() ) {
v = min(v,maxValue(u.ls.front()));
u.ls.pop_front();
}
return v;
}
For you can help me better I will make clear the meaning of some variables:
winner: is the position the computer will move
u.moves: is the depth on the search tree , for root is 0
m: supposed to save the less depth state solution , for that way filter solutions and computer must play the move more close of solution.
check: save utility value at this moment for known if is a terminal state
utility for win is 700 for tie is 0 and for defeat is -700
u.ls: list of children states
Something else , I think use m and winner global and return a global on minimax is a poor solution , do you can see some way to improve this?
Thanks very much.
First things first, what does u.getUtility() return if the state is not terminal? If it returns 0, well then 0 % 700 == 0 is true, so it's just finding the first move it expanded and selecting it. Since I can't see the u.makeDescendents() algorithm, I can't rule this out.
If that's not the case, then almost certainly your u.getUtility() function is making the assumption that it is only ever being called for the same max player. i.e. It's returning 700 if X wins and -700 if X loses. If you're running both sides through the same minimax, then when you evaluate O as max, it's still trying to find a win for X because that's the only time it will see the evaluation as a win.
If this is the case, the fix is simple, determine which player's turn it is from the state and return the win/loss evaluation as if it were that player (which is typically always a loss in TicTacToe because you cannot make a move which loses you the game, you can only win by making a move and the previous player made the last move).
If neither of these suggestions solve the problem, the typical way to debug minimax problems is to step through the game tree one level deep at a time, exploring the path that is returning known invalid evaluations until you find the point at which is generates an incorrect value. Then you have to inspect it as to find out why. This is trivial for small games like tic tac toe, because it only goes 9 levels deep and you can get a perfect minimax value, but for any non trivial game, you generally have to look at your evaluation function to determine where the discrepancy is occurring.
I am writing a quicksort program. For that I need to partition the array. The partitioning is done by a function paritionIt(). I wrote a code of partitioning the array which is as follows:
int partition(int beg,int end,double key)
{
int pLeft = beg;
int pRight = end-1;
while(pLeft<pRight)
{
while(array[++pLeft]<key);
while(array[--pRight]>key);
if(pLeft<pRight)
swap(pLeft,pRight);
}
swap(pLeft,end-1);
return pLeft;
}
This block seems to work to work fine when executed in isolation. However, when ran along with the other functions, it seems to generate wrong answer. The following code given to me makes all the problems vanish but it doesn't seem much different from my code.
int partitionIt(int left, int right, double pivot)
{
int leftMark = left; //right of first elem
int rightMark = right - 1; //left of pivot
while(true)
{
while( theVect[++leftMark] < pivot ) //find bigger
; // (nop)
while( theVect[--rightMark] > pivot ) //find smaller
; // (nop)
if(leftMark >= rightMark) //if pointers cross,
break; // partition done
else //not crossed, so
swap(leftMark, rightMark); //swap elements
} //end while(true)
swap(leftMark, right-1); //restore pivot
return leftMark; //return pivot location
} //end partitionIt()
The block seems to be similar to mine but is giving the right answer whereas mine is not. Can you please me by telling what's the difference between partition() and partitionIt().
The difference is where you're breaking out of your looping structure.
In your code, you're making two conditional checks, whereas in the given code, you're only making one.
Assume you've been iterating through the loop for a while. (No pun intended).
You'll hit this code:
if(pLeft<pRight)
swap(pLeft,pRight);
Then you'll hit the bottom of the while loop, come back to the top, and then check again if pLeft<pRight. If this isn't true, we exit the loop.
In the given code, you perform the swap, but then you do the following:
while( theVect[++leftMark] < pivot ) //find bigger
; // (nop)
while( theVect[--rightMark] > pivot ) //find smaller
; // (nop)
You then check to see if you break out of the loop.
This seems to be where the difference lies.
Edit: To clarify - what happens if while(pLeft>=pRight) when you first enter the loop?
In the given code, you continue through the while loop until it breaks, but in your code, you never enter the body of the loop.
The only thing I see immediately is that the functions will
behave differently if called with left + 1 == right: your
function will not enter the loop, but will return beg; the
function from the book will enter the loop, thus incrementing
leftMark and decrementing rightMark before doing the final
swap and returning leftMark.
I have a vector holding 10 items (all of the same class for simplicity call it 'a'). What I want to do is to check that 'A' isn't either a) hiding the walls or b) hiding another 'A'. I have a collisions function that does this.
The idea is simply to have this looping class go though and move 'A' to the next position, if that potion is causing a collision then it needs to give itself a new random position on the screen. Because the screen is small, there is a good chance that the element will be put onto of another one (or on top of the wall etc). The logic of the code works well in my head - but debugging the code the object just gets stuck in the loop, and stay in the same position. 'A' is supposed to move about the screen, but it stays still!
When I comment out the Do while loop, and move the 'MoveObject()' Function up the code works perfectly the 'A's are moving about the screen. It is just when I try and add the extra functionality to it is when it doesn't work.
void Board::Loop(void){
//Display the postion of that Element.
for (unsigned int i = 0; i <= 10; ++i){
do {
if (checkCollisions(i)==true){
moveObject(i);
}
else{
objects[i]->ResetPostion();
}
}
while (checkCollisions(i) == false);
objects[i]->SetPosition(objects[i]->getXDir(),objects[i]->getYDir());
}
}
The class below is the collision detection. This I will expand later.
bool Board::checkCollisions(int index){
char boundry = map[objects[index]->getXDir()][objects[index]->getYDir()];
//There has been no collisions - therefore don't change anything
if(boundry == SYMBOL_EMPTY){
return false;
}
else{
return true;
}
}
Any help would be much appreciated. I will buy you a virtual beer :-)
Thanks
Edit:
ResetPostion -> this will give the element A a random position on the screen
moveObject -> this will look at the direction of the object and adjust the x and Y cord's appropriately.
I guess you need: do { ...
... } while (checkCollisions(i));
Also, if you have 10 elements, then i = 0; i < 10; i++
And btw. don't write if (something == true), simply if (something) or if (!something)
for (unsigned int i = 0; i <= 10; ++i){
is wrong because that's a loop for eleven items, use
for (unsigned int i = 0; i < 10; ++i){
instead.
You don't define what 'doesn't work' means, so that's all the help I can give for now.
There seems to be a lot of confusion here over basic language structure and logic flow. Writing a few very simple test apps that exercise different language features will probably help you a lot. (So will a step-thru debugger, if you have one)
do/while() is a fairly advanced feature that some people spend whole careers never using, see: do...while vs while
I recommend getting a solid foundation with while and if/else before even using for. Your first look at do should be when you've just finished a while or for loop and realize you could save a mountain of duplicate initialization code if you just changed the order of execution a bit. (Personally I don't even use do for that any more, I just use an iterator with while(true)/break since it lets me pre and post code all within a single loop)
I think this simplifies what you're trying to accomplish:
void Board::Loop(void) {
//Display the postion of that Element.
for (unsigned int i = 0; i < 10; ++i) {
while(IsGoingToCollide(i)) //check is first, do while doesn't make sense
objects[i]->ResetPosition();
moveObject(i); //same as ->SetPosition(XDir, YDir)?
//either explain difference or remove one or the other
}
}
This function name seems ambiguous to me:
bool Board::checkCollisions(int index) {
I'd recommend changing it to:
// returns true if moving to next position (based on inertia) will
// cause overlap with any other object's or structure's current location
bool Board::IsGoingToCollide(int index) {
In contrast checkCollisions() could also mean:
// returns true if there is no overlap between this object's
// current location and any other object's or structure's current location
bool Board::DidntCollide(int index) {
Final note: Double check that ->ResetPosition() puts things inside the boundaries.
Here is my code for checking if future move is legal, I have assumed its legal and copied move into mySquares array. I then call this method in the game cycle set in the form and in the timer handler which is:
canvas->drawGrid();
testBlock->drawBlock();
testBlock->moveDown();//this method has checkBounds for when hit sides, top & bottom
if(newBlock->canMoveDown()==false)
{
newBlock->addMySelfToGameBoard();
mainGameBoard->updateGrid();
}
//timer1 handler finish
bool TTetrisBlock::canMoveDown()
{
array<Point>^ temporaryCopy = gcnew array<Point>(4);
bool canGoDown = true;
for(int i=0;i<mySquares->Length;i++)
{
//Set future move
temporaryCopy[i].X = mySquares[i].X;
temporaryCopy[i].Y = mySquares[i].Y+1;
}
//Check if future move cells are full, if not assign values to mySquares
//Check if future move is legal
for(int j=0;j<temporaryCopy->Length;j++)
{
if(gameBoard->isCellOccupied(temporaryCopy[j].X,temporaryCopy[j].Y) == true)
{
mySquares[j].X = temporaryCopy[j].X;
mySquares[j].Y = temporaryCopy[j].Y;
}
}
return canGoDown;
}
//end of moveDown
in my gameboard class i have the method which checks if TCell is occupied or not. TGameBoar holds an array of TCells which has a color and bool isOccupied = false;
bool TGameBoard::isCellOccupied(int c,int r)
{
//Checks if TCell is occupied
return myGrid[c,r]->getIsOccupied();
}
It Crashes and indicates here was the problem, Im currently learning C++ at school. I would appreciate some help. I am also struggling with the Keydown for moving left and right using e->KeyData == Keys::Left) etc. and creating a newblock when gone through loop.
I have my project rar if you want to check it out. I have all the classes done, its just putting it together is the hard bit.
Project Tetris
I see three problems.
First you should only move mySquares when isCellOccupied returns false (not true as you currently have it). I suspect this is the cause of your crash as it looks like you will be moving a block into a cell that is already occupied.
Second, when isCellOccupied returns true you should set canGoDown to false and break out of your for loop (or better yet, make canGoDown (==true) an additional condition of your for loop i.e. j < temporaryCopy->Length && canGoDown). As it is, your function always return true because it is never set to false and that can't be right.
Just making an assumption here, but don't all mySquares consist of 4 elements? You are initializing temporaryCopy with 4 elements but it isn't clear whether mySquares has 4 elements. If not, this could be dangerous as in your first loop you are looping on mySquares->Length and addressing temporaryCopy with that index value, which could be out of range. And then later doing the opposite. It might be better to use a constant (4) in all all loops or better yet, always use mySquares->Length (especially when creating the temporaryCopy array) to ensure that both arrays contain the same number of elements.