• Post Reply Bookmark Topic Watch Topic
  • New Topic

tic tac toe Console Game.  RSS feed

 
Ranch Hand
Posts: 87
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So im making a tic tac toe and trying to figure out different ways to check for winning moves, i accomplished this by just writing out all the different possibilitys.....easy enough but then i wanted to come up with a system that could tell if a player won no matter what size the board was.

Option one: a 3x3 board you can tell by the absolute value when going down and putting the spaces in a array. 00 = a1, 01= b1, 02 = c1, 10 = a2 ect. a1 in the array a1 and b1 are 3 from each other b1 and c1 are three from each other. well this way actually takes a bit more code then i thought. even though it seemed interesting. (feel free to expand on this.)
a1
b1
c1
Now i am trying this: basically creating a while loop,

when userX/Oturn runs i have it basically doing this: out "player (name) enter space" into toLower.string = userMove.
now when i check if the users answer arrayBoard.equals(userMove) checking from one of the arrays from main (mentioned in the above method) should i use a switch to check through the array or just a for
loop with some if statements in it??? any other ideas you have go right ahead.

also the for loop seems the best. any other ideas on how to check for a winner no matter the board size?
 
Sean Paulson
Ranch Hand
Posts: 87
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
here is the call to the players move thoughts???
 
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Sean,

It kinda depends on how the rules change with the size of the board. For instance, do you always need a sequence of the same length as the size of the board, or can it be arbitrary (like making a sequence of 4 Xs on a board that's 5x6)?

A solution that works for any size with most rules is performing 4 for-loops: check horizontally from the last mark you made on the board, check vertically, and check the two diagonals. Increment a counter by 1 for each cell that contains the same mark as the one you just placed, and reset the counter otherwise. If the counter reaches the required total, the player that made the mark wins. I would also separate your interaction with the console from your interaction with the game. Make a class that represents a game of TicTacToe, and give it methods that clearly reflect how a game is played. Here's what it could look like:
 
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sean Paulson wrote:So im making a tic tac toe and trying to figure out different ways to check for winning moves,

Actually, what you appear to be doing is checking for a winning position in the abstract, when if fact all you need to do is check for a winning move.

What's the difference? To check for a winning position, you need to look at the entire board (as you are); but to check for a winning move, you only need to work out what it changed.

Take tic-tac-toe on an N x N board, and assuming you do this check after every move:
Suppose I place an 'O' on row r and column c - ie, position(r, c).
Suppose further that the move is valid - ie, position(r, c) is not already occupied.

To find out if it is a winning move:
1. Check if row r is all 'O's.
2. Check if column c is all 'O's.
3. If my move was on one of the diagonals (and there are TWO), check if that diagonal is all 'O's.
Obviously, one of those diagonals - and the one to check for first - is where r == c; I'll let you work out how to check for the other one yourself.

The reason to check for r == c first is that if N is odd, the board will have a "centre" position which lies on both diagonals.

If none of the row, column, or (possibly) diagonals changed by the move is entirely made up of the symbol that was used, then the game can continue.

HIH

Winston
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:to check for a winning move, you only need to work out what it changed...

Actually, if you want to get really clever, you could give each symbol a value; and keep totals for each row, column and diagonal.

Easiest is as follows:
Empty square = 0.
'O' = 1.
'X' = N + 1 (for an N x N board).

Again, assuming a valid move to position(r, c):
1. Add the symbol value to rowTotal[r].
2. Check if rowTotal[r] indicates a winning position.
3. Add the symbol value to columnTotal[c].
4. Check if columnTotal[c] indicates a winning position.
5. if r == c:
  5a. Add the symbol value to downWardDiagonalTotal.
  5a. Check if downWardDiagonalTotal indicates a winning position.
6. Ditto for the "upward" diagonal.
.
And the total check is the same in all cases, ie:
If total == (symbol value * N) then you have a winning position.

It should be mentioned that there are limitations to this approach. If your totals are all ints, then the limit for N is ≈46340   (√Integer.MAX_VALUE).

HIH

Winston
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It should be noted that that approach can only be used if the sequence is equal to the size of the board. If you can win with smaller sequences (say, a three-in-a-row on a 5x5 board) then it won't work.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:It should be noted that that approach can only be used if the sequence is equal to the size of the board. If you can win with smaller sequences (say, a three-in-a-row on a 5x5 board) then it won't work.

Very true. And you'd then need some way of checking for "sequences" as well.

But it's still the case that you only have to check for them in the row/column/diagonals affected by the move.

Winston
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Agreed.
 
Sean Paulson
Ranch Hand
Posts: 87
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yes actually what i ended up doing is creating two for loops and changing the createBoard array from createBoard[] to createBoard[][]
That way i could creat a for loop in each players call playerOne() playerTwo() (player one is 'x' and player two is 'o'

rowCheck[3] colCheck[3]
for(row)for(col)if createBoard[row][col].equals "x" then add 1 to rowOne[row] if rowOne[row] == 3 then playerX wins

then switch the for loops to check the columns for a win then a separate statement for each of the diags

basically i would share it but i actually stepped in over my head on this one and had not learned enough returning variables and such basic stuff but i learned alot and am going to try again and clean it up then i will post it here.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please share with us when you've gotten ahead, I'm very curious
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sean Paulson wrote:basically i would share it but i actually stepped in over my head on this one and had not learned enough returning variables and such basic stuff but i learned alot and am going to try again and clean it up then i will post it here.

OK, but don't worry too much about getting it absolutely right. This is a beginners' forum, so we don't expect "perfect" programs.

And like Stephan, I'd be interested to see what you come up with.

Winston
 
Sean Paulson
Ranch Hand
Posts: 87
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
sorry if its a little cluttered i got to go to work but here it is

 
Sean Paulson
Ranch Hand
Posts: 87
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
also i know there is no tie game scenario
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tested it with the sequence b2, a3, b1, b3, a1, c3, a2, c1, c2. It doesn't show that player 2 wins after c3.

Sean, you're not using the power of object oriented programming. You're not using classes effectively, and your methods are very long and do too much. Do you know how to create objects? Do you know the difference between static and non-static methods?

You need to break up your application into multiple classes that each have a responsibility. You can have a Board class that keeps track of where the marks were placed, a Game class that keeps track of the state of the game, and a Main class that interacts with the console and the game.

Your class names should start with a capital letter, and should be descriptive: banana starts with a lowercase letter, and it's name is misleading, to say the least.

You're using multiple Scanners to read from System.in. This is not necessary, one is enough.

String is an immutable class. It's methods return new Strings, they don't modify the old one. That means statements like checkE.toLowerCase(); are useless. Instead, you should do something like this: checkE = checkE.toLowerCase();

Use descriptive names. It's not clear what checkE means. If it's used to check whether the user wants to exit, use a boolean userWantsToExit instead.

Your userXturn() and userOturn() methods do almost exactly the same. There's a lot of code duplication. You can probably change them into one method that has a parameter indicating which player's turn it is; although if you have a Game class, you don't need to, because the Game can keep track of who's turn it is internally. The same is true for checking who wins the game: there's a lot of code duplication that can be removed.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One more tip: you declare a lot of variables outside the scope they're used, and you're assigning them unused values.

If you want to declare variables to use in a for-loop, you can declare them inside of the loop header. It's also convention to make the upper bound on the number of iterations exclusive. So instead of this:

You can do this:

However, it's best not to hardcode "magic values". You can declare constants in your class, and use those instead:
 
Sean Paulson
Ranch Hand
Posts: 87
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks Stephan and yes you are right i do not know what static and non static is i have glanced at it but i was really just writing this to practice what i have learned so far, and no i kinda know what objects are im going to read more about it this weekend and rewrite this program more OOP.
i do have some questions about that though. objects are variables or functions that are within other methods right(even though i thought functions and methods were the same thing??) and my methods should be alot smaller and basically do one task right then i just do this = object.methodFrom other function. like that?? and im guessing thats why its called object oriented programming insted of method OP...yes i know im very astute haha.

also i named it banana because this file was originally my hello world that i named randomly haha but yes i am having trouble finding java standards in any of my learning materials.
ill look over the rest of your post tomorrow or fri i just worked 12hrs and gota do the same tomorrow so im pretty tired.

ps it is not showing a win for player 2 at all.....hmmm i might look into it or just rewrite it with objects??..
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hope you had a good day, and that you have some good rest.

Yes, as a next step, I recommend reading more about objects.

Think of all the things you interact with as objects. The grid you use to place marks on is an object, the names of the players are objects, etc.

All objects are of some type. In your application, the type of your board is String[][]. Instead of String[][], it would be much easier if your board was of type Board.

Variables are not objects. Variables hold references to objects. Methods are operations that are applied to objects. There is a very small difference between methods and functions, but forget the word function for now, because in Java the word is not really used.

The difference between a static and a non-static method is that a non-static method needs to be called on an object, while a static method can be called from thin air. Using too much static methods usually indicates that you're not thinking about objects enough. For instance, instead of doing something like showBoard(boardSpaces), it would be much nicer to do something like board.show().

Anyway, don't let me confuse you too much now. When you're ready, read about these concepts here: https://docs.oracle.com/javase/tutorial/java/concepts/index.html
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sean Paulson wrote:i do have some questions about that though. objects are variables or functions that are within other methods right

No. Objects are instances of a class; and the business of a class is to define something useful. Now that "something useful" might well include other "things" which are themselves objects, but it's not a requirement.

The main difference between an Object-Oriented language like Java and older ones like C or BASIC is that those languages only allow you to define methods and have a very limited set of data types - usually things like integers and Strings and decimals - whereas an OO language allows you to define classes, which combine methods and data in a single unit; and that unit can then be used anywhere else in your program as a "type".

Those older languages are called "procedural" because they usually involve writing programs as a set of instructions. For example:
Suppose somebody gave you the pieces of a carburettor for a car and asked you to put it together, you might well find the task impossible to do because the order in which you do things is essential to the job. If you put flange C in place before you've finished dealing with bracket B, you may find it impossible to tighten all the screws because they're now covered by the flange.
So you need a set of instructions that tells you what to do and (most importantly) when to do it - and this is very similar to the instructions of a procedural language:
"insert bracket B; tighten screws in rotation; add flange C..."

However, there are problems which, though still relatively simple, are quite complicated to describe as a single set of instructions. Do you know how to ride a bike? Many of us do, and once we master the business of "turning into the direction you're falling" we can do it quite easily. But could you write a program to do it?
Have you ever watched someone balance a pole on the end of their finger, or a helicopter hovering in place during a rescue. If you look closely, they're doing all sorts of minor corrections in real time to allow for changes in direction or wind speed. Could you write a set of instructions to do that?

The trouble is that these kinds of problems don't fit neatly into the "do this; then do this; then do this..." style because there are several things going on at once, and each has an effect on the others.


And this is where having objects really come into its own: Because each object has methods and data, we can get them to do things that would be very difficult for a single set of instructions. It's almost like having several mini-programs, each with its own set of instructions, that can "talk to" and react with each other.

The trouble is that thinking "objectively" is more difficult for us puny humans. We like "do this; do that; do the other..." instructions because they're easy to understand, and we can follow them in our mind, but trying to connect several of them together and thinking about all the possibilities makes our tiny brains explode.

Another problem is that Java is a bit of a "hybrid" language. You can write large amounts of procedural code, and that's what you're doing at the moment. Eventually you'll learn how to get away from that style and think in terms of objects, but for most of us it doesn't come naturally. But don't worry; you'll get there in the end.

You might be interested to read my WhatNotHow article. Even if you don't understand it completely right now, it'll give you a few things to think about.


BTW, in answer to your other question: The difference between a function and a method is that a function usually takes a value (or two, or three...) and returns a result, without any outside effects - ie, it's completely self-contained.
So, for example:
  double sqrt(int n) { ...
that calculates the square root of a number, would be a function; but:
  void setPrice(double newPrice) { ...
that sets the price of a product, would be a method (and you'd probably write it for a Product class).

In Java terms, they're both methods, but the first one has the characteristics of a "function".

HIH

Winston
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!