Original Post

I decided to make a one-player Tic-Tac-Toe game. Yes, I know DogP made a Tic-Tac-Toe game, but (no offense) it isn’t really playable. I tried looking at the source code and it all looks like gibberish. So, I’m trying to make my own here. I’ve posted what I have so far (which isn’t very much besides a fancy title screen). I think I may be able to pull this off, but I need a little help, though. What I want to do with the logic is have a turn counter, and, depending on whose turn it is (the computer or yours), go to a different section of code. What I would normally do in a basic-like structure is, “if turn=1 then goto turn_1, if turn=2 then goto turn_2”, etc., So how would I do this in C without using the goto command? Any simple example code will do.

Attachments:
50 Replies

The easiest way would be:

if (turn==1)
{
  //do player's turn stuff here
}
else
{
  //do computer AI here
}

If that’s a little messy (could be, depending how much code you have), you could use a function like:

void player_turn()
{
  //do player's turn stuff here
}

void computer_turn()
{
  //do computer AI here
}

if (turn==1)
  player_turn();
else
  computer_turn();

DogP

OK, everything seems to be working fine except there is no win detection. I need a somewhat simple way to detect wins. In my code, if X (you) win, the value of message should be 1 and if O (the computer) wins, the value of message should be 2. You can transpose these numbers if you want, but if message equals 0, then the game is still being played. Once I add win detection, I can go ahead and add some more features.

Attachments:

It’s kind of easy to win.

No offense, but, your code is a bit of a mess too. Ever heard of indentation? Comments? You could also make the ifs a bit shorter like this:

Before:

	if (turn==1) 
		computer_turn();
		
	if (turn==3)
		computer_turn();
		
	if (turn==5)
		computer_turn();
		
	if (turn==7)
		computer_turn();
		
	if (turn==9)
		computer_turn();

After:

	if (turn==1 | turn==3 | turn==5 | turn==7 | turn==9) computer_turn();

Or even better, for this particular case:

	if (turn % 2) computer_turn();

Yes, I know my code is a mess. As you can see, I’m not very good at C. And I was going to add some AI after I figure out how to get win detection.

What if there’s no win but a draw?

That should actually be:

	if ((turn==1) || (turn==3) || (turn==5) || (turn==7) || (turn==9)) computer_turn();

You need each condition in (), and you should use “logical or” ||, not “bitwise or” | .

And from a quick look at the code, I have no idea what’s going on (some comments would be nice :P). Where are Xs and Os stored? TTT is a very simple game and there’s only 9 spaces, so if you’re looking for “win detection”, after a tile is placed, just call a function like win_detect();

Then since there’s only a few combinations that can win, inside that function do something like:

//place_XY is the TTT grid, 00 is upper left, 20 is upper right, 22 is lower right
//unused is 0, X is 1, O is 2
	if (((place_00==1)&&(place_01==1)&&(place_02==1)) || ((place_10==1)&&(place_11==1)&&(place_12==1))) X_wins();

That’s inefficient, but who cares… just fill that in with the rest of the logic. Or you could do something like summing each line, and checking if ==3 or ==6.

DogP

There’s also the switch/case structure:
http://www.cprogramming.com/tutorial/lesson5_tg.html

I just took a brief look at your code and… Gah! No offense, but it looks like you need to learn arrays, man! All of that variable declaration at the beginning:

int xpos1=0, opos=0, circle1x=0, circle1y=0;
int cross2x=0, cross2y=0, xpos2=0, xpos=0;
int circle2x=0, circle2y=0, opos1=0, opos2=0;
int cross3x=0, cross3y=0;
int circle3x=0, circle3y=0, opos3=0, opos4=0;
int cross4x=0, cross4y=0; int circle4x=0, circle4y=0, opos5=0;
int cross5x=0, cross5y=0; int circle5x=0, circle5y=0;

…could be replaced with

int oPos[5], xPos[5];
int crossX[5], crossY[5];
int circleX[5], circleY[5];

If you’re struggling with C, I suggest the tutorials at cplusplus.com. C++ is basically C with additional features, but the language is mostly the same up to object oriented programming. Hope that helps!

By the way, is C your first language, or are you more familiar with another programming language?

  • This reply was modified 14 years, 7 months ago by Fwirt.

I just added a whole bunch of comments. Hope they help to understand what’s going on here. Also, I think all the arrays stuff is over my head. Remember that I’m used to BASIC programming and all this C stuff is somewhat still new to me.

Okay, seriously, you guys are all making way too big a deal over figuring out if it is the computer or human turn. The quickest and easiest way is to use a mask…

if (turn & 0x01 == 0x01) {
 /* Player A turn */
} else {
 /* Player B turn */
}

OK, I think I have a win detection routine down. See if this works. I tested it and it seemed to work for X.

Attachments:

mbuchman wrote:
Okay, seriously, you guys are all making way too big a deal over figuring out if it is the computer or human turn. The quickest and easiest way is to use a mask…

if (turn & 0x01 == 0x01) {
 /* Player A turn */
} else {
 /* Player B turn */
}

Well… there’s a difference between writing someone’s code and helping them understand it. I wouldn’t try to explain bitmasks to someone who doesn’t understand arrays.

Chris: It doesn’t seem to work correctly… it seems to stop at times when the game isn’t over. Like:

XX
  O
OX

DogP

mbuchman wrote:
Okay, seriously, you guys are all making way too big a deal over figuring out if it is the computer or human turn. The quickest and easiest way is to use a mask…

if (turn & 0x01 == 0x01) {
 /* Player A turn */
} else {
 /* Player B turn */
}

You know, now that you bring that up, why do you even need to mask it and check for equality when you could just do:

if (turn && 0x01)

But like DogP said, I don’t think this is really helping Chris understand C any better.

Sorry Chris, but I really highly recommend that you learn arrays. I know it seems hard, but they’ll save you a ton of work compared to what you’re doing right now. For a thorough and specific tutorial on arrays, look here. Arrays are just a list of variables that you can access by number. So instead of having to write code that has a ton of if statements and deals with each variable seperately, you only need 1 line of code, and a number (which can be a variable) that tells you which line to access.
For an example… Instead of this:

if (myVar == 1)
  thing1 = 5;
else if (myVar == 2)
  thing2 = 5;
else if (myVar == 3)
  thing3 = 5;
//etc...

Arrays let you do this:

thing[myVar] = 5;

Well worth the effort of learning them, no?

(If you think the transition from Basic to C is hard, my first language was actually Javascript8-O, which is a pretty horrible language)

Fwirt wrote:
You know, now that you bring that up, why do you even need to mask it and check for equality when you could just do:

if (turn && 0x01)

Heh, I was gonna point that out too, though I didn’t want to drag this too far off topic. But since you brought it up, that should have been:

if (turn & 0x01)

With the logical AND (&&), it would have evaluated true any time turn was non-zero. The bitwise AND (&) masks the last bit, evaluating true only when the corresponding bit of turn is 1.

DogP

DogP wrote:
Heh, I was gonna point that out too, though I didn’t want to drag this too far off topic. But since you brought it up, that should have been:

if (turn & 0x01)

With the logical AND (&&), it would have evaluated true any time turn was non-zero. The bitwise AND (&) masks the last bit, evaluating true only when the corresponding bit of turn is 1.

DogP

Thanks for catching that. I hate it when I mix up bitwise and boolean and/or >:(.

Looking through my code for my Tic-Tac-Toe game for the TI83+, I had an epiphany. So I made each square have its own value. Then, checking to see if the values were one (human) or two (computer), I’d need only eight if statements per player to check for a win, not the tons of code I had been doing. Duh, I’m stupid.

  • This reply was modified 14 years, 7 months ago by VirtualChris.
  • This reply was modified 14 years, 7 months ago by VirtualChris.
Attachments:

DogP, I understand your point. I just didn’t like how many solutions were being suggested when such an elegant solution existed!

And after reviewing my earlier post, I realize I came off as a jerk, sorry!

DogP wrote:

Fwirt wrote:
You know, now that you bring that up, why do you even need to mask it and check for equality when you could just do:

if (turn & 0x01)

Heh, I was gonna point that out too

Basically, it is a good habit to always use a relational or equality operator in every if/while/for statement to make sure your intentions are properly implemented and easily understood by others. I think it is even a MISRA rule, but I am not 100% sure and don’t have a copy handy.

So I used the “== 0x01” style for clarity, and let the compiler optimize out unnecessary C code. “((turn & 0x01) == 0x01)” will automagically be converted to “(turn & 0x01)” by the compiler. But by writing it with the “== 0x01” my code should have been more readable, especially being it follows the same pattern as a multi-bit mask would.

-Matt

Chris,

The TI calculators allow you to use arrays. You could start learning about them by trying to implement them on your calculator. And better yet, the book that came with your calculator should tell you how to program with arrays.

I think arrays seem over my head right now. I looked at the site provided, but it all seems so complicated.

What is MISRA?

Added some text. Mainly a wins/losses/ties counter and a message saying “YOU WIN”, “YOU LOSE”, or “TIE GAME”. Since there can only be three slots for stuff, I put the text in 3, which means when the game is going on, the cursor is shown, but when the game is decided, the text is shown and the cursor disappears. What I want to know is how to get rid of the half-squares that show up once the text disappears and the cursor comes back. By the way, I forgot to mention that this is my entry for the 2010 competition, so I added the required “Planet Virtual Boy” start-up screen.

Attachments:

 

Write a reply

You must be logged in to reply to this topic.