I started studying C a week ago and decided to write my own tic-tac-toe game for practise.
I have a game loop in main:
for(int i = 1; player1.isWinner!=1 || player2.isWinner!=1 || noWinner!=1; i++){...}
Where i - counts turns and condition of end of the game is one of players has won, or no one has won (draw).
For now, it quits executing only if all conditions are 1.
How can I make it work right?
Is a value of 1 where someone won?
If so, then you would need check any of those conditions is true and loop if they are not:
!(player1.isWinner==1 || player2.isWinner==1 || noWinner==1)
Or using AND, check and loop when none are set:
(player1.isWinner!=1 && player2.isWinner!=1 && noWinner!=1)
Consider extracting the condition to a well-named function in order to aid readability and maintanability:
int hasWinner(/*...*/)
{
return player1.isWinner == 1 || player2.isWinner == 1 || noWinner == 1;
}
It then becomes obvious what the condition should be:
for(int i = 1; !hasWinner(/*...*/); i++){ /*...*/ }
You seem to be using some sort of backwards boolean logic. If 1 represents the boolean value true, then the condition should be
!(player1.isWinner || player2.isWinner || noWinner)
This assumes that you set player1.isWinner to 1 when player1 has won.
It would probably be easier to use bool with values true or false from stdbool.h.
Related
The code below shows the rowtotal[0], which is the return value I'm getting from an infinite loop for every iteration. I'm trying to break the loop when all three returned values from the costcheck array are the same. This is my code:
do
{
.
.
.
/*do loop body*/
.
.
costcheck[counter3]=rowtotal[0];
if(costcheck[counter3-2]==costcheck[counter3] &&
costcheck[counter3-1]==costcheck[counter3] )
{
response=1;
}
counter3++;
printf("\t\t\t Number of iterations: %d \r", stop++);
}
while(response!=1);
Just get rid of all strange, superfluous variables. You only need to save the result of the previous iteration, together with a counter which you increase each time you find a match, rather than every time in the loop.
int counter=0;
const int COUNT_N = 3;
data_t prev=FORBIDDEN; // a value that rowdata[0] can never have
while(counter != COUNT_N)
{
...
if(prev == rowdata[0])
{
counter++;
}
else
{
counter=0;
}
prev = rowdata[0];
}
just to elaborate on Lundins Answer wich is the way to go in my opinion (would have posted as a comment, but lacking reputation...)
Only thing missing is the actual loop advancement counter (counter3 in your example):
int quitCounter=0; // Counter for quiting the loop on 3 consecutive identical values
int loopCounter=0; // Your normal rowdata index
const int QUIT_COUNT_N = 3;
#define FORBIDDEN 0xffffff // or some other value that rowdata[0] can never have
data_t prev=FORBIDDEN; // a value
do
{
...
/* do loop body, provide new value for rowtotal[0] on each iteration */
/* if you need to store the consecutive values returned in rowtotal[0] in costcheck array,
make sure that it will be big enough - if you only need to break on 3 identical values,
you can skip the entire costcheck array as Lundin proposes. */
...
costcheck[counter3]=rowtotal[0];
if(prev == costcheck[counter3])
{
quitCounter++;
}
else
{
quitCounter=0;
}
prev = costcheck[counter3];
counter3++;
} while(quitCounter!= QUIT_COUNT_N )
If you really want an infinite loop, a if(costcheck[counter-1] == costcheck[counter-2] && costcheck[counter-2] == costcheck[counter-3]) will lead to failure of program, if costcheck array has less than 3 elements. You have to be sure that it does have at least 3 elemets in this array.
BUT!!!! counter does not need to be more than 3 because as far as i get it, you want to check 3 most reciently read elements. Which means for comparison, you only need to remember 3 last values that were read.
The exapmple below stores up to 3 rowtotal[0] values, and checks if they are equal. If they are, progarm exits, if not, program gets new rowtotal[0] to the "end" of costcheck array, also the oldest value: here it's costcheck[0] is lost.
I can post the code to the example which i made, to show how the logic should work.
NOTE!!! I strongly think Lundin's and Morphine's solutions are by far better than mine.
do
{
.............
if(counter < 3)
{
costcheck[counter] = rowtotal[0];
counter++;
continue;
}
else
{
if(costcheck[counter-1] == costcheck[counter-2] && costcheck[counter-2] == costcheck[counter-3])
{
response=1;
}
else
{
costcheck[counter-3] = costcheck[counter-2];
costcheck[counter-2] = costcheck[counter-1];
costcheck[counter-1] = rowtotal[0];
}
}
}
while(response!=1);
}
I'm trying to make a small function that checks whether a spot is taken on a Tic Tac Toe board or not. I have created an array of zeroes called tttArray where when each spot is filled, its location is changed to 1. So I first take the input from the player from the below function.
function [pXInputRow, pXInputCol] = pickXspot(playerInput)
%This function is to take inputs from Player X
pXInputRow = 0;
pXInputCol = 0;
%Set text for Row/Col Prompt
prompt = {'Row (1,2, or 3)', '(Col (1, 2, or 3)'};
name = 'Player X Turn';
%Show prompt to input values
playerInput = inputdlg(prompt, name);
pXInputRow = str2num(playerInput{2});
pXInputCol = str2num(playerInput{1});
tttArray(pXInputRow, pXInputCol) = 1;
end
And then use the below function to see if the spot is taken.
function [spotTaken] = checktaken(tttArray)
%Function used to check if spot is taken
%Setup Error Messages
errorMessage = 'This spot is taken, please choose another spot';
errorMessageTitle = 'Spot Taken';
if tttArray(pXInputRow, pXInputCol) || tttArray(pOInputRow, pOInputCol) == 1
msgbox(errorMessage, errorMessageTitle)
spotTaken = 1;
end
end
However, I keep getting the following error after I run and put a row/col in the prompt dialog box. Any Suggestions?
Not enough input arguments.
Error in checktaken (line 8)
if tttArray(pXInputRow, pXInputCol) || tttArray(pOInputRow, pOInputCol) == 1
Couple of problems.
You supplied the tttArray as an input parameter to your checkTaken function as a call argument:
function [spotTaken] = checktaken(tttArray)
but you do not appear to have supplied the row and column parameters pXInputRow, pXInputCol or pOInputRow, pOInputCol as arguments.
So those parameters are undefined when you call
if tttArray(pXInputRow, pXInputCol) || tttArray(pOInputRow, pOInputCol) == 1
You need to supply those coordinates as arguments to your checkTaken function.
You could do the brute force method
function [spotTaken] = checktaken(tttArray, pXInputRow, pXInputCol, pOInputRow, pOInputCol)
or you could do something more elegant like put the coordinates in an array.
Another problem is if you want to check if either of the array elements is equal to 1, your if statement syntax is not correct.
in effect you have
if a || b == 1
but that is probably not what you want. Se the Matlab documentation on operator precedence
Instead you probably want
if (a == 1) || (b == 1)
so you if statement should be
if (tttArray(pXInputRow, pXInputCol) ==1) || (tttArray(pOInputRow, pOInputCol) == 1)
I am having trouble with the while loop in my code. The instructions say to "Set a loop-control variable to a value that automatically enters the loop for the first time". Any suggestions on how I can do this? Any input will be appreciated. Thank you!
}//end main
I will assume you don't know what most of these terms mean.
A while loop assumes the following syntax (I'll do it in C# since I'm not sure what language you're coding in; update your original post and I'll change my samples):
while (/* loop control/condition here */)
{
// Code here
}
This evaluates like this in english (pseudocode):
while the loop control is true
do this
when it equals false leave the while
So what you want to do is initialize a variable (I'm using type bool here for clarity's sake) and put it in between the parenthesis as the "loop control."
Here's a small sample:
bool daytime = true; // This is the loop control.
int i = 0;
while (daytime == true) // We are seeing if it's day out.
{
System.out.println("It is daytime.");
if (i == 6) {daytime = false;} // If our counter hits 6:00 it's nighttime.
i = i + 1; // Increment our counter.
}
Anyway hope that helps you. Good luck!
Edit: Do-While
I may have misunderstood your original question a bit, this is what a do-while loop looks like:
Syntax:
do
{
// Code here
} while (/* loop control/condition here */);
Pseudocode:
do this code
keep repeating code until the condition is false
Sample:
bool daytime = true; // This is the loop control.
int i = 0;
do
{
System.out.println("It is daytime.");
if (i == 6) {daytime = false;} // If our counter hits 6:00 it's nighttime.
i = i + 1; // Increment our counter.
} while (daytime == true) // We are seeing if it's day out.
i have a problem in c like this:
I have a problem in the code below. The problem is this that i doing some addition part after both if conditions break.And that addiion is repeatative while loop until count>0 The problem is if i put braces in for loop then it repeats the the part inside the braces until it's condition is not false. Buti have to do addition which is like this:
We have an array data[i].freq={0,1,2,3,4,5} and data[i].next represents the next member to be added.Suppose i add 0 and 1 first i got"1" as a result and i put the result in last index of my array , like this ({0 1 2 3 4 5 1})now 0 and 1 cann not be added because they are already added(i don't have to repeat the addition on same elements), so next time the addition will be between the last index element and smallest element before the last element (but not those elements who are already added). so here the addition will be between the "1" in last index+ smallest element in right to it which is "2" Note here we have not taken in acount 0 and 1 because they are already added, the same way this 2 will not be added next time because it is being added this time and their addition wil be {0 1 2 3 4 5 1 3} we have to repeat the same until there left & element at last.
data[data_size].freq=data[i].freq+data[p].freq; // here i add the first 2 elements "0" and "1" in the example i given below.
int count=5;
do
{
for(i=0;data[i].next!=-1;i=data[i].next)//the problem is here if i put bracesit dont't do the ask which i expect it to do.
if(data[data[i].next].freq>data[data_size].freq && data[data[i].next].flag==0)
break;
data[data_size+1].freq= data[data_size].freq+ data[data[i].next].freq;
data[data_size].next=data[i].next;
data[i].next=data_size;
data_size++;
if(data[data[i].next].freq<data[data_size].freq && data[data[i].next].flag==0)
break;
data[data_size+1].freq= data[data_size].freq + data[i].freq
data[data_size].next=data[i].next;
data[i].next=data_size;
data_size++;
count--;
} while(count>0)
could any one please help me in desiging the code for what i want to achieve.
If you write
for(i=0 ..any condition)
if(condition1)
break;
if(condition2)
break;
you don't only have an unreadable mess, but you also have only the first if clause in the for loop.
If you want the for loop to extend over both, you must put them into {}:
for(...) {
if(condition1) break;
if(condition2) break;
}
My personal preference is to always use braces when the statements are in the next line. S don't write
if(condition1)
break;
as someone could be tempted to insert an andditional statement and be surprised that it doesn't work as it should, but either do
if(condition1) break;
in one line or
if(condition1) {
break;
}
add braces which are not needed for functionality, but for readability.
This is how the compiler sees your code:
int count=5;
do
{
for (i = 0; data[i].next != -1; i = data[i].next)
{
if (data[data[i].next].freq > data[data_size].freq && data[data[i].next].flag == 0)
break; // break out of the enclosing 'for' loop (goes to point A)
}
// Point A
data[data_size].next = data[i].next;
data[i].next = data_size;
data_size++;
if (data[data[i].next].freq < data[data_size].freq && data[data[i].next].flag == 0)
{
break; // break out of the outer 'do' loop (goes to point B)
}
data[data_size].next = data[i].next;
data[i].next = data_size;
data_size++;
count--;
} while (count > 0);
// Point B
Based on your code comments, I think your problem is that your 'break' statements are not taking you where you think they're taking you.
I'm quite new to programming and have recently started in Processing.
In my code, the collide function sets the touch boolean to be true but by arraying it, it only tests true for the final array and not the ones before it. Where am I going wrong here? I hope my question is clear enough.
edit:
Sorry, let me try again.
I guess my problem is finding out how to array the collide function properly. I cant seem to add a [i] for the collide in the array.
At the moment, the code works but it only tests true for the last array and not for the ones before it.
The array code:
for(int i = 0 ; i < lineDiv; i++){
collide(xPts[i], yPts[i], vecPoints.xPos, vecPoints.yPos, myDeflector.Thk, vecPoints.d);
The collide function:
void collide(float pt1x, float pt1y, float pt2x, float pt2y, int size1, int size2){
if (pt1x + size1/2 >= pt2x - size2/2 &&
pt1x - size1/2 <= pt2x + size2/2 &&
pt1y + size1/2 >= pt2y - size2/2 &&
pt1y - size1/2 <= pt2y + size2/2) {
touch = true;
}
else{
touch=false;
}
Your "touch" variable is global. Every time you call the collide() function, it overwrites whatever it was set to before. Perhaps you just want to test if touch is true after calling collide(), then exit the for loop?
Alternatively, you may want to make collide() return the touch boolean, avoiding the global.
It looks like what you want to do is to run through a loop, run the function on that element of the array and return a value if any of them are true. This is my best guess, you might want to edit your question to clarify what you are looking to do. So assuming this:
1) change you method to a function
boolean collide(float pt1x, float pt1y, float pt2x, float pt2y, int size1, int size2){
if (pt1x + size1/2 >= pt2x - size2/2 &&
pt1x - size1/2 <= pt2x + size2/2 &&
pt1y + size1/2 >= pt2y - size2/2 &&
pt1y - size1/2 <= pt2y + size2/2) {
return true;
}
else{
return false;
}
2) change your loop and how you are calling it
touch = false; // if you don't set this to false before the loop, it will be the last value taken
for(int i = 0 ; i < lineDiv; i++){
if (collide(xPts[i], yPts[i], vecPoints.xPos, vecPoints.yPos, myDeflector.Thk, vecPoints.d)) touch = true;
Before the action would be that touch might cycle between true and false as you iterate through the array and in processing (because you would likely draw out the data) it is unlikely that you would want this behavior because you wouldn't be able to do anything with it unless you packed that data in another structure like an array.
So now, the "touch" is set to false and will change to true if any function calls return a true. If all are false, it will stay false.
note: you might consider using either xPts.length() or yPts.length() vs lineDiv. This would reduce the possibility of a array out of bounds exception assuming xPts and yPts have the same # of elements.