I have created an array full of letters and I'm stuck on implementing the function for the cell to randomly move in one of 8 directions (N, NE, E, SE, S, SW, W, NW). I've used a switch statement for the basic 4 direction but couldn't figure out the other 4 directions.
void randomStep()
{
if ((island[ro][co + 1] != ('B'||'L') || co == NUMROWS - 1 )&& (island[ro + 1][co] != ('B'||'L') || ro == NUMCOLS -1) && (island[ro - 1][co] != ('B'||'L') || ro == 0)
&& (island[ro][co - 1] != ('B'||'L') || co == 0))
break;
int direction = rand() % 8;
switch (direction) {
case 0: if (co < NUMROWS - 1 && island[ro][co + 1] == 'B'||'L'){ //move right
co++;
break;
}
case 1: if (ro < NUMCOLS -1 && island[co + 1][ro] == 'B'||'L') { //move down
ro++;
break;
}
case 2: if (ro > 0 && island[ro - 1][co] == 'B'||'L'){ //move up
ro--;
break;
}
case 3: if (co > 0 && island[ro][co - 1] == 'B'||'L') { //move left
co--;
break;
}
You can simply combine the conditions and results of two other cases. Here is an example for NW (left and up)
case 4: if (ro > 0 && co > 0 && island[ro - 1][co - 1] == 'B'||'L') { //move up & left
ro--;
co--;
}
break;
Note that I have moved the position of the break; to be outside the if code block.
I think you may also have an error with
... island[ro - 1][co - 1] == 'B'||'L' ...
which I guess should be
... island[ro - 1][co - 1] == 'B' || island[ro - 1][co - 1] == 'L' ...
and similarly in the other cases.
You can move parts of your code into functions:
bool mayGoUp(int ro, int co)
{
return ro > 0;
}
bool mayGoDown(int ro, int co)
{
return ro < NUMROWS - 1;
}
bool mayGoLeft(int ro, int co)
{
return co > 0;
}
bool mayGoRight(int ro, int co)
{
return co < NUMCOLS - 1;
}
Note: I changed the logic a bit: from co < NUMROWS - 1 to co < NUMCOLS - 1; not sure which one is the correct one.
Then you can combine them in a straightforward way:
bool mayGoUpLeft(int ro, int co)
{
return mayGoUp(ro, co) && mayGoLeft(ro, co);
}
Then, using them in your code will make your code clearer:
switch (direction) {
case 0:
if (MayGoRight(ro, co) && island[ro][co + 1] == ...
{ //move right
co++;
break;
}
...
case 99:
if (MayGoUpRight(ro, co) && ...
{ // move up and right
ro--;
co++;
break;
}
Related
I'm a complete newbie, so please excuse me.
I tried using online compiler but they unresponsive, and I get no return value (or return 0 for whatever I enter)
I tried to write a function that check if triangle is right, isosceles or both, and return 1,2,3 respectively, all other cases should return 0.
int main() {
int TriangleType(unsigned angle1, unsigned angle2) {
unsigned angleSum = angle1 + angle2;
if (angleSum >= 180) {
return 0;
}
/* if triangle is right ---> */
if (angle1==90 || angle2==90 || angleSum==90) {
/*if it is also an isosceles --->*/
if (angle2==45 || angle1==45) {
return 3;
}
return 1;
}
/*check if it only a isosceles*/
if (angle1==(180-angle2)/2 ||
angle2== (180-angle1)/2 ||
angle1==angle2) {
return 2;
}
return 0;
}
TriangleType(110, 111);
}
First, don't try to use nested functions in C. Pulling that function out of main.
int TriangleType(unsigned angle1, unsigned angle2) {
unsigned angleSum = angle1 + angle2;
if (angleSum >= 180) {
return 0;
}
/* if triangle is right ---> */
if (angle1==90 || angle2==90 || angleSum==90) {
/*if it is also an isosceles --->*/
if (angle2==45 || angle1==45) {
return 3;
}
return 1;
}
/*check if it only a isosceles*/
if (angle1==(180-angle2)/2 ||
angle2== (180-angle1)/2 ||
angle1==angle2) {
return 2;
}
return 0;
}
int main() {
TriangleType(110, 111);
}
Second, this doesn't do anything with the return value from the function, so of course you see no output.
int main(void) {
switch (TriangleType(110, 111)) {
case 1:
printf("Right triangle\n");
break;
case 2:
printf("Isosceles triangle\n");
break;
case 3:
printf("Both types\n");
break;
default:
printf("None of the above\n");
}
return 0;
}
Code is functionally wrong
Even after re-organizing and moving the nested function, code attempts to be clever and not perform simple tests.
if (angle1 == (180 - angle2) / 2 || angle2 == (180 - angle1) / 2 || angle1 == angle2) fails in cases like TriangleType(45,89) --> 2 as (180 - angle2) / 2 rounds down. angle1 * 2 == (180 - angle2) would make more sense.
TriangleType(90, 90), where the 3rd angle is 0, returns 0. That is asymmetric. TriangleType(0, 90), TriangleType(90, 0) do not return 0.
TriangleType(0, 0) returns 2. I would expect that to return 0, a rejected triangle.
Below is a test harness for OP to use and test TriangleType().
#include <stdio.h>
int TriangleType(unsigned angle1, unsigned angle2) {
unsigned angleSum = angle1 + angle2;
if (angleSum >= 180) {
return 0;
}
/* if triangle is right ---> */
if (angle1 == 90 || angle2 == 90 || angleSum == 90) {
/*if it is also an isosceles --->*/
if (angle2 == 45 || angle1 == 45) {
return 3;
}
return 1;
}
/*check if it only a isosceles */
if (angle1 == (180 - angle2) / 2 || angle2 == (180 - angle1) / 2
|| angle1 == angle2) {
return 2;
}
return 0;
}
int my_TriangleType(unsigned angle1, unsigned angle2) {
unsigned angle3 = 180 - angle1 - angle2;
if (angle1 >= 180 || angle2 >= 180 || angle3 >= 180) {
return 0;
}
if (angle1 == 0 || angle2 == 0 || angle3 == 0) {
return 0;
}
int retval = angle1 == 90 || angle2 == 90 || angle3 == 90 ? 1 : 0;
if (angle1 == angle2 || angle2 == angle3 || angle3 == angle1)
retval += 2;
return retval;
}
#include <string.h>
#define MAX_LIMIT 127
int main() {
printf("score:%d my_score:%d\n", TriangleType(45,89), my_TriangleType(45,89));
int error_count = 0;
int flags[4][4] = {0};
for (unsigned angle1 = 0; angle1 <= 181; angle1++) {
for (unsigned angle2 = 0; angle2 <= 181; angle2++) {
int score = TriangleType(angle1, angle2);
int my_score = my_TriangleType(angle1, angle2);
if (score != my_score) {
error_count++;
if (flags[score][my_score] == 0) {
flags[score][my_score] = 1;
printf("%3d angle1:%2u angle2:%2u score:%d my_score:%d\n", //
error_count, angle1, angle2, score, my_score);
}
}
}
}
printf("total errors:%d\n", error_count);
return 0;
}
Output:
score:2 my_score:0
1 angle1: 0 angle2: 0 score:2 my_score:0
2 angle1: 0 angle2:90 score:1 my_score:0
total errors:181
another_TriangleType() could be made that is more efficient than my_TriangleType(), yet it would needed to functionally match.
Well your questions is lacking some information, but I assume you got as inputs of your program, two angles.
THe fisrt thing we need to think is:
If you got a right triangle, than there is one of those values equals 90 degrees, instead the sum of them must be 90.
On the other hand, if you got an isosceles triangle you should have 2 equal values, instead you must have the 180 deg - sum of both angles should result in one of those two.
Let's try to code this out:
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define RIGHT 0x01
#define ISOSCELES 0x02
#define BOTH 0x03
// If you got a right triangle, than there is one of those values equals 90 degrees, instead the sum of them must be 90.
int bIsRightTriangle(int iAngDeg1, int iAngDeg2){
if ( iAngDeg1 == 90 || iAngDeg2 == 90 )
return TRUE;
if ( (iAngDeg1 + iAngDeg2) == 90 )
return TRUE;
return FALSE;
}
// On the other hand, if you got an isosceles triangle you should have 2 equal values,
// instead you must have the 180 deg - sum of both angles should result in one of those two.
int bIs_IsoscelesTriangle(int iAngDeg1, int iAngDeg2){
int iAngDeg3 = 180 - iAngDeg1 + iAngDeg2;
if ( iAngDeg1 == iAngDeg2 )
return TRUE;
if ( (iAngDeg3 == iAngDeg1) || (iAngDeg3 == iAngDeg2) )
return TRUE;
return FALSE;
}
int iGetTriangleTypeByAngles(int iAngDeg1, int iAngDeg2){
int iReturnType = 0;
iReturnType = bIsRightTriangle(iAngDeg1, iAngDeg2) ? (iReturnType | RIGHT) : iReturnType;
iReturnType = bIs_IsoscelesTriangle(iAngDeg1, iAngDeg2) ? (iReturnType | ISOSCELES) : iReturnType;
return iReturnType;
}
int main(int argc, char *argv[]){
if ( argc < 3 ){
return -1;
}
// In case you want an output
// printf("%d\n", iGetTriangleTypeByAngles(atoi(argv[1]), atoi(argv[2])));
return iGetTriangleTypeByAngles(atoi(argv[1]), atoi(argv[2]));
}
I have the code below, but I need the code to account for white spaces and double digits, for example if i enter (7-3)/(2+2) it should come out 73-22+/ result: 1. If i enter (7 - 3) / (2 + 2) it should come out 7 3 - 2 2 + / result 1. If I enter (22 - 10)/(2 + 2) it should come out 22 10 - 2 2 + / Result: 3
Here is the code I have:
#include<stdio.h>
char stack[100];
int top = 0;
int eval_top = -1;
int eval_stack[100];
void push(char x) // Push char into stack
{
stack[top++] = x;
}
char pop() // Pop char to top of stack
{
if (top == -1)
return -1;
else
return stack[top--];
}
/* functions for evaluation of postfix expression */
// push function
void eval_push(int x) { // Find push result
eval_stack[++eval_top] = x;
}
// pop function
int eval_pop() { // Find pop result
if (eval_top == -1) {
return -1;
} else {
return eval_stack[eval_top--];
}
}
int priority(char x) // check priority order
{
if (x == '(')
return 0;
if (x == '+' || x == '-')
return 1;
if (x == '*' || x == '/')
return 2;
}
// function to evaluate the postfix expression
void EvalPostfix(char postfix[]) {
int A, B;
int val;
char ch;
int i;
//find postfix
for (i = 0; postfix[i] != ')'; i++) {
ch = postfix[i];
if (isdigit(ch)) {
eval_push(ch - '0');
} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
A = eval_pop();
B = eval_pop();
switch (ch) {
case '*':
val = B * A;
break;
case '/':
val = B / A;
break;
case '+':
val = B + A;
break;
case '-':
val = B - A;
break;
}
eval_push(val); //send value on top of stack
}
}
printf("\n Result: %d \n", eval_pop());
}
main() {
int i = 0;
char * e, x;
char postfix[100]; // store postfix for later evaluation
char exp[100];
printf("Infix expression : ");
scanf("%s", exp); // asking the user to enter the infix expression
printf("Postfix expression: ");
e = exp;
while ( * e != '\0') {
if (isalnum( * e)) { // if character is alphabet or number , it is printed
printf("%c", * e);
postfix[i++] = * e;
} else if ( * e == '(') // if it is open parenthesis, it is pushed into the stack without any priority
push( * e);
else if ( * e == ')') // if it is closed parenthesis , pop the elements in the stack and print them until the we see ( symbol
{
while ((x = pop()) != '(') {
printf("%c", x);
postfix[i++] = x;
}
} else // if character is symbol like +, -, *, / then based on their priority character is pushed if it high priority otherwise high priority symbols are popped and it is pushed
{
while (priority(stack[top]) >= priority( * e)) {
x = pop();
printf("%c", x);
postfix[i++] = x;
}
push( * e);
}
e++;
}
while (top != -1) // printing remaining elements in the stack
{
x = pop();
printf("%c", x);
postfix[i++] = x;
}
postfix[i] = ')'; // this is to add at the end for detecting end by the evaluation function
EvalPostfix(postfix);
}
There are some problems in your code
your pop is not symmetric with your push, push post increment the index so pop must pre decrement the index, and because of that the first invalid index is not -1 but 0 :
char pop() // Pop char to top of stack
{
if (top == 0)
return -1;
else
return stack[--top];
}
priority does not return a value if all the tests are false, but probably the last test is useless
In
while (priority(stack[top]) >= priority( * e))
you missed to check if the stack is empty, must be :
while ((top != 0) && (priority(stack[top]) >= priority( * e))) {
Because the first invalid index for stack is 0 rather than -1
while (top != -1) // printing remaining elements in the stack
must be
while (top != 0) // printing remaining elements in the stack
When you make the postfix expression there is no separation between the numbers, for instance "12+3" becomes "123+" like "1+23", and in EvalPostfix you consider a number has only one digit (eval_push(ch - '0');), so you do not manage the numbers having more than 1 digit. To manage several digits add a separator after all numbers, for instance a space to have "12 3 +" or "1 23 +" and read the number with scanf etc
You do not make the right postfix expression in all the cases, for instance for 1+2*3 you make 12+3* but it must be 123*+
You do not detect the invalid infix expressions
in
while (priority(stack[top]) >= priority( * e))
I missed to say the top element is not stack[top] but stack[top - 1] so it must be replaced by
while ((top != 0) && (priority(stack[top - 1]) >= priority( * e))) {
adding that correction 1+2*3 produces the right postfix expression 123*+
Note it is more clear to introduce the function empty() and tops(), and in case of an invalid access into the stack print a message and exit rather than to return -1 as a char
int empty()
{
return (top == 0);
}
char tops()
{
if (top == 0) {
fputs("top() on the empty stack, abort", stderr);
exit(-1);
}
return stack[top - 1];
}
char pop() // Pop char to top of stack
{
if (top == 0) {
fputs("pop() on the empty stack, abort", stderr);
exit(-1);
}
return stack[--top];
}
also detect a possible overflow of the stack :
void push(char x) // Push char into stack
{
if (top == sizeof(stack)) {
fputs("stack overflow", stderr);
exit(-1);
}
stack[top++] = x;
}
so now you can do
while (!empty() && (priority(tops()) >= priority( * e))) {
Of course this is the same for the other stack
I need the code to account for white spaces and double digits
double digits is too restrictive, just manage any integer, for that you can extract the number using strtol. You cannot also read the full expression using scanf("%s", exp); because is stops on the first space, use fgets.
This is the verification from a connect four game prototype, but it seems I've done something wrong.
I want that everytime the player is making a move, the function will verify if there he won or not, by verifying vertically, horizontally, and eventually, on the diagonal.
But it seems that it does not verify correctly, because in some cases, even though there are only 2 moves made, the functions returns 1.
int verifyGame(int gamePosition, int gameVariable, char gameArray[HEIGTH][WIDTH])
{
if(gameArray[gamePosition][gameVariable] == gameArray[gamePosition + 1][gameVariable] == gameArray[gamePosition + 2][gameVariable] == gameArray[gamePosition + 3][gameVariable]) //verify vertically
return 1;
else
if(gameArray[gamePosition][gameVariable] == gameArray[gamePosition][gameVariable - 3] == gameArray[gamePosition][gameVariable - 2] == gameArray[gamePosition][gameVariable - 1]) //verify horizontally
return 1;
else
if(gameArray[gamePosition][gameVariable] == gameArray[gamePosition][gameVariable - 2] == gameArray[gamePosition][gameVariable - 1] == gameArray[gamePosition][gameVariable + 1])
return 1;
else
if(gameArray[gamePosition][gameVariable] == gameArray[gamePosition][gameVariable - 1] == gameArray[gamePosition][gameVariable + 1] == gameArray[gamePosition][gameVariable + 2])
return 1;
else
if(gameArray[gamePosition][gameVariable] == gameArray[gamePosition][gameVariable + 1] == gameArray[gamePosition][gameVariable+ 2] == gameArray[gamePosition][gameVariable + 3])
return 1;
//verify diagonally
else return 0;
};
This is where the function is called. The switch verifies the users input, and then it places the value in the matrix, and then verifies for won
printf("playerPick is : %d\n", playerPick);
fflush(stdout);
switch(playerPick)
{
case 1:
if(gameVariables[0] >0 && gameVariables[0] < 7)
{
--gameVariables[0];
gameArray[gameVariables[0]][0] = (char) 82;
ifWon = verifyGame(gameVariables[0], 0, gameArray);
}
printArray(gameArray);
break;
case 2:
if(gameVariables[1] >0 && gameVariables[1] < 7)
{
--gameVariables[1];
gameArray[gameVariables[1]][1] = (char) 82;
ifWon = verifyGame(gameVariables[1], 1, gameArray);
}
printArray(gameArray);
break;
case 3:
if(gameVariables[2] >0 && gameVariables[2] < 7)
{
--gameVariables[2];
gameArray[gameVariables[2]][2] = (char) 82;
ifWon = verifyGame(gameVariables[2], 2, gameArray);
}
printArray(gameArray);
break;
case 4:
if(gameVariables[3] >0 && gameVariables[3] < 7)
{
--gameVariables[3];
gameArray[gameVariables[3]][3] = (char) 82;
ifWon = verifyGame(gameVariables[3], 3, gameArray);
}
printArray(gameArray);
break;
case 5:
if(gameVariables[4] >0 && gameVariables[4] < 7)
{
--gameVariables[4];
gameArray[gameVariables[4]][4] = (char) 82;
ifWon = verifyGame(gameVariables[4], 4, gameArray);
}
printArray(gameArray);
break;
case 6:
if(gameVariables[5] >0 && gameVariables[5] < 7)
{
--gameVariables[5];
gameArray[gameVariables[5]][5] = (char) 82;
ifWon = verifyGame(gameVariables[5], 5, gameArray);
}
printArray(gameArray);
break;
case 7:
if(gameVariables[6] >0 && gameVariables[6] < 7)
{
--gameVariables[6];
gameArray[gameVariables[6]][6] = (char) 82;
ifWon = verifyGame(gameVariables[6], 6, gameArray);
}
printArray(gameArray);
break;
}
printf("%d %d %d %d %d %d %d\n", gameVariables[0], gameVariables[1], gameVariables[2], gameVariables[3], gameVariables[4], gameVariables[5], gameVariables[6]);
printf("ifwon : %d\n", ifWon);
#Weather Vane's answer is correct. The logic used in your original post is not correct for a verification.
One reason you may not have caught it yourself may be the complicated way it was written. Try simplifying the user input verification code: (Range checking the user input values is all that is necessary.)
//User input range checking:
if((gamePosition >= x)&& //where `x` is minimum for gamePosition
(gamePosition <= y)&& //where `y` is maximum for gamePosition
(gameVariable >= z)&& //where `z` is minimum for gameVariable
(gameVariable <= w)) //where `w` is maximum for gameVariable
{//continue }
else
{
printf("Invalid value. Please re-enter");
return -1;
}
Another opportunity for simplification is to note that each of your case statements contain identical code, with the exception of the value of the case. Because of this the entire switch(...){...} can be replaced with a single if statement:
//assuming playerPick >= 1
if(gameVariables[playerPick-1] >0 && gameVariables[playerPick-1] < 7)
{
--gameVariables[playerPick-1];
gameArray[gameVariables[playerPick-1]][playerPick-1] = (char) 82;
ifWon = verifyGame(gameVariables[playerPick-1], playerPick-1, gameArray);
}
printArray(gameArray);
Also note that although the statement:
gameArray[gameVariables[0][0] = (char) 82; //what is 82?
is perfectly legal, the variable gameArray[0][0] is just a char, so casting the value 82 is not necessary. Also, C syntax provides a way to pull out the ASCII decimal value of the character by surrounding it with the graves symbol, allowing the following form, which is more readable:
gameArray[gameVariables[0]][0] = `R`; //intuitive
You cannot chain equality testing as you are attempting. The code will execute, but not as you suppose. Your code
if(gameArray[gamePosition][gameVariable] ==
gameArray[gamePosition + 1][gameVariable] ==
gameArray[gamePosition + 2][gameVariable] ==
gameArray[gamePosition + 3][gameVariable])
must be split up into individual tests, such as:
if(gameArray[gamePosition][gameVariable] == gameArray[gamePosition + 1][gameVariable] &&
gameArray[gamePosition][gameVariable] == gameArray[gamePosition + 2][gameVariable] &&
gameArray[gamePosition][gameVariable] == gameArray[gamePosition + 3][gameVariable])
and on the other lines too.
I'm doing homework for UNI and I got to do a Tic-Tac-Toe without any decision taken by player, the moves are all chosen randomly. So if the character on matrix is ' ' it means it's free, while if it's 'X' or 'O' it should generate another move. This is the code (language C):
if (playerTurn == 1){
playerSymb = 'X';
}
else if (playerTurn == 2){
playerSymb = 'O';
}
if (matrix[rand1][rand2] == ' '){
matrix[rand1][rand2] = playerSymb;
} else if(matrix[rand1][rand2] == 'X' || matrix[rand1][rand2] == 'O'){
do{
randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
}while (matrix[randAlt1][randAlt2] != 'X' && matrix[randAlt1][randAlt2] != 'O');
matrix[randAlt1][randAlt2] = playerSymb;
}
I did not copied the whole code because it's not finished at all, i just need help solving this. But if I try to run this, the Symbols can be overwritten, like if I have a 'X' at matrix[1][2], it's possible that it will be a 'O' after some turns. So how can I make moves do not overwrite? (sorry for bad english).
Just put correct condition:
while (matrix[randAlt1][randAlt2] == 'X' || matrix[randAlt1][randAlt2] == 'O')
(i.e. try again if this cell is not empty)
Also it is easy to simplify your code without loosing of anything:
randAlt1 = rand1;
randAlt2 = rand2;
while (matrix[randAlt1][randAlt2] != ' ') {
randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';
And it is better to add loop guard to prevent infinite loop (or to add special checks for this case):
randAlt1 = rand1;
randAlt2 = rand2;
int nbAttempts = 0;
while (matrix[randAlt1][randAlt2] != ' ' && nbAttempts < 100) {
randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
nbAttempts++;
}
if (matrix[randAlt1][randAlt2] != ' ') {
// show error message and stop the game
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';
You choose an arbitrary position and then test if it is free – possibly multiple times. But you can also choose a number of a free position and then find it.
First set up a turn counter
int turnNo = 0;
then make a loop for alternate moves, which chooses one of 9-turnNo unused positions, finds it, marks is with a player mark and tests if the move made a line of three:
while(turnNo < 9)
{
char currPlayerMark = ...choose 'X' or 'O';
int freePos = 9 - turnNo;
int currPos = rand() % freePos; // 0 .. freePos-1
for(x=0; x<3; x++)
{
for(y=0; y<3; y++)
{
if(matrix[x][y] == ' ') // a free position
if(--currPos < 0) // the sought one
break; // break the inner loop
}
if(currPos < 0)
break; // break the outer loop
}
matrix[x][y] = currPlayerMark;
if(test_for_win_position(x,y))
{
message_a_win_of_player(currPlayerMark);
break; // turnNo < 9 here
}
turnNo ++;
}
Finally test if the loop terminated with no 'win':
if(turnNo == 9)
message_its_a_draw(); // no-one wins
A function to test the win position might look like this:
int test_for_win_position(int x, int y)
{
char mark = matrix[x][y];
// check a column
if(matrix[x][0] == mark && matrix[x][1] == mark && matrix[x][2] == mark)
return 1;
// check a row
if(matrix[0][y] == mark && matrix[1][y] == mark && matrix[2][y] == mark)
return 1;
// check one diagonal
if(x==y)
if(matrix[0][0] == mark && matrix[1][1] == mark && matrix[2][2] == mark)
return 1;
// check another diagonal
if(x+y==2)
if(matrix[0][2] == mark && matrix[1][1] == mark && matrix[2][0] == mark)
return 1;
// current player has not won (yet)
return 0;
}
i am having a problem figuring out an algorithm for this problem,been trying for few days without success,here is a pic of what im trying to obtain:
http://i.stack.imgur.com/X70nX.png
Here is my code tried many differents solutions but always get stuck at the same point:(Sorry for mixed language the important part is in english)
ps
im not supposed to use functions to solve this problem only loops and array.
EDIT
after much fixing it does the walk but seldomly crashes
any idea?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void){
char box[10][10];
int i,j;
int move,row,col;
char letter='A';
srand(time(NULL));
printf("\n\tSTART\n\n");
for(i=0;i < 10 ;i++)/* righe */
{
for(j=0;j < 10;j++) /* colonne */
{
box[i][j] = '.'; /* assegno . a tutti gli elementi dell array */
if(j == 9)
printf("%c%c\n", box[i][j]); /* giustifico ogni 10 elementi dell array j(0-9) */
else
printf("%c%c", box[i][j]);
}
}
/* LETS START */
printf("\n\n Inizia il gioco\n\n");
/* random place to start */
row = rand() % 9;
col = rand() % 9;
box[row][col]= 'A';
while(letter <= 'Z')
{
if(box[row+1][col] == '.' || box[row-1][col] == '.' || box[row][col+1] == '.' || box[row][col-1] == '.' )
{
move=rand() % 4;
switch(move){
case 0: /* Going UP */
if((row != 0) && (box[row-1][col] == '.'))
{
box[row-1][col]=++letter;
box[row--][col];
}else{
move=rand() % 4;
}
case 1:/* Going Down */
if((row != 9) && (box[row+1][col] == '.'))
{
box[row+1][col]=++letter;
box[row++][col];
}else{
move=rand() % 4;
}
case 2: /*Going Left */
if((col != 0) && (box[row][col-1] == '.'))
{
box[row][col-1]=++letter;
box[row][col--];
}else{
move=rand() % 4;
}
case 3: /* Going Right */
if((col != 9) && (box[row][col+1] == '.') )
{
box[row][col+1]=++letter;
box[row][col++];
}else{
move=rand() % 4;
}
}
}else{
printf("\n\nBloccato a %c\n\n", letter);
break;
}
}
/* FINE */
for(i=0;i<10;i++)/* righe */
{
for(j=0;j<10;j++) /* colonne */
{
if(j == 9)
printf("%c%c\n", box[i][j]); /* giustifico ogni 10 elementi dell array j(0-9) */
else
printf("%c%c", box[i][j]);
}
}
return 0;
}
You need to update row and col inside the loop.
Otherwise you'll always attempt to walk from the position of the 'A'.
... and once all 4 directions are filled, you're stuck in a infinite loop
. . . . .
. . B . .
. E A C .
. . D . .
Even when you update row and col inside the loop (and correct the == mistake), you have to handle a problem: suppose the first spot (the 'A') is the top left corner and the next random directions are East, South, South, West, and North. ... now what? :)
A B .
F C .
E D .
. . .
It's not a good idea to "reroll" the random number when you discover that you cannot go in some direction, because if you have bad luck, you get the same number twice (or even 3 or 4 or more times) - so even if you generated 4 random numbers and they all failed, that doesn't mean that you're stuck.
You can solve this problem by generating one number, and trying all 4 possible directions starting from it:
If the random number generator returned 0: check 0, 1, 2, 3
If the random number generator returned 1: check 1, 2, 3, 0
If the random number generator returned 2: check 2, 3, 0, 1
If the random number generator returned 3: check 3, 0, 1, 2
Implemented by the following code:
desired_move = rand();
success = 0;
for (i = 0; i < 4 && !success; ++i)
{
move = (desired_move + i) % 4;
switch (move)
{
case 0: // Go up
if (row > 0 && box[row - 1][col] == '.')
{
row = row - 1;
success = 1;
}
break;
case 1: // Go down
...
}
}
if (!success) // Tried all 4 directions but failed! You are stuck!
{
goto START_OVER; // or whatever else
}
Note that this algorithm is not very random: if you cannot go up, there is a greater chance that you go down than right or left. If you want to fix it, you can pick a random permutation of 4 directions instead of checking the directions sequentially:
const int permutation_table[24][4] = {
{0, 1, 2, 3},
{0, 1, 3, 2},
{0, 2, 1, 3},
...
{3, 2, 1, 0}
};
index = rand() % 24;
for (i = 0; i < 4; ++i)
{
move = permutation_table[index][i];
switch (move) {
... // As above
}
}
When you're in for loop.
Draw a possible direction
int direction = rand()%4;
Check all possible directions if the drawed one is invalid (not in array or not a ".")
int i=-1;
while( ++i < 4 )
{
switch(direction)
{
case 0:
if( row-1 >= 0 && box[row-1][col] == '.' ) {
--row;
i = -1;
}
break;
case 1:
if( col+1 < 10 && box[row][col+1] == '.' ) {
++col;
i = -1;
}
break;
case 2:
if( row+1 < 10 && box[row+1][col] == '.' ) {
++row;
i = -1;
}
break;
case 3:
if( col-1 >= 0 && box[row][col-1] == '.' ) {
--col;
i = -1;
}
break;
}
if( i != -1 ) {
direction = (direction+1)%4;
}
else {
break;
}
}
If there's no valid move end the for loop>
if( i == 4 ) {
break;
}
Otherwise write a letter to the table cell and update row/col position.
box[row][col] = letter;
And... that's all I guess. This is greedy algorithm so you don't need any optimizations (at least I don't see any in exercise requirements.
It looks like you are breaking out of your switch statement if you try to go in a direction that isn't valid, but you increment your counter anyway. Try to check another random direction if that happens.
where exactly does it break?
from what I can see at a glance is that you have a chance that It_that_walks gets in position from witch it cant go anywhere:
A B C D .
. I J E .
. H G F .
where after J?
There is no need for the && (box[row][col-1]= '.')
Allso, it is wrong (assignment instead of comparison), it should be: && (box[row][col-1]== '.') (but you dont need it alltogether)