I've made a tictactoe game using ncurses functions such as mvaddch to put x and o on my board. I need to somehow find the locations of the x's and o's so that i can win my game, and i have no idea how to do this.
I've made a tictactoe game using ncurses functions such as mvaddch to put x and o on my board. I need to somehow find the locations of the x's and o's so that i can win my game, and i have no idea how to do this.
I suggest you keep a copy of the board in a more convenient "format" for checking whether a square is occupied, whether somebody won, or it's a cat's game. A tic-tac-toe board is basically a 3x3 array where each cell can be X, O or empty. A 3x3 array of char is good, you can intialize it to ' ' (space) for a new, empty board. As a player moves, place the 'X' or 'O' in the appropriate space. So take a declaration like char board[3][3].
Now, you will need functions to translate screen coordinates to your 3x3 board (for input) and board to screen for output. How exactly you do that depends on how you draw your board and how you get user input. You must know the position on the screen of the user input to draw it and put the X's and O's, so find a way to correlate that to your board. I think curses uses the upper-left corner as the origin, (0, 0). That also means that board[0][0] could represent the upper-left of your tic-tac-toe board.
Hope that helps. Can't help you much more without knowing how you display the board and get input.
i drew the board with mvaddch function for example mvaddch (i,0, '|'); but 3 different times.
So are you saying to use the 3x3 array all empty like "char board[3][3];"?
i also drew my x and o with the same mvaddch function sooo it pretty much just replaces that space
with an x or o. Should i put a counter so that everytime and x or o is placed add a counter to the array?
You don't need a counter, you simply initialize the board to all spaces, like so:
That is an empty board. Then, if the user places an 'X' in the middle row, right column, you doCode:char board[3][3]; for (r = 0; r < ; r++) { // row for (c = 0; c < 3; c++) { // column board[r][c] = ' '; } }
Of course, you want to check if that spot is available before you allow the move. Also, you don't want to hard-code the relationship between screen coordinate and board coordinate, there is a more convenient way to do it (see below).Code:board[1][2] = 'X';
To check for a win, e.g. across the top row, you check if board[0][0], board[0][1] and board[0][2] are the same char ('X' or 'O'). If they are, that person won. You do the same for all 3 rows, all 3 columns, and both diagonals. You check after every move.
Note, you haven't provided an actual description of your screen, or exactly how you get input, so the following is just an example of how to do it. You need a way to map the screen coordinates to your board coordinates. Note, below, I am using coordinates "backward" from normal, i.e. with the y (vertical/row) coordinate first. That matches the indexing in the board array, and the order of parameters to mvaddch. For example, if your screen looks like:
That board is drawn on your screen, with the upper-left of the board at some coordinate on the screen, say (y, x) = (10, 25). I will call that coordinate the "anchor". The upper-left spot in your board is then at (10, 25), the upper right at (10, 29), the lower right at (14, 29) and the middle spot at (12, 27). Remember, you need space forCode:| | -+-+- | | -+-+- | |
When the user places an X or an O on your board, you must know the position of that X or O, so you can draw it correctly (you did say you can draw the board fine with mvaddch). You pass mvaddch(y, x, ch) a y (row) and x (column) to draw the character (ch). You simply need to find a way to map the y and x screen coordinates to row/column for your board. From the above example
Pretty simple really, you subtract the appropriate anchor coordinate, and divide by 2. Note, depending on your screen layout, you may have to use a different formula, but the idea is the same.Code:y (screen) -> row (board) 10 -> 0 12 -> 1 14 -> 2 x (screen) -> column (board) 25 -> 0 27 -> 1 29 -> 2
Work with that for a while, then if you're still stuck post your code and me or somebody else will be along to help.
So after i made the 2d array would i use if statements to change the array values as the person enters a number?
I think you need to explain to us how the user selects where they want to go. The simplest way for you (the programmer) is for them to specify 2 numbers -- row and column.
Borrowing anduril462's diagram:
The O is in row 0 column 0 and the X is in row 1 column 2. You'd read two numbers from the user, and then access the array as anduril462 described. You don't need any 'if' statements to change the value of the array -- but you do need to check that the space isn't filled etc.Code:O| | -+-+- | |X -+-+- | |
If on the other hand you're think each square has a single number:
Then you'll need to translate the number into array indices. One possible way to do this is with if statements, there are others but do what's easiest.Code:1|2|3 -+-+- 4|5|6 -+-+- 7|8|9
Or did you mean something else?
I used a switch statement and for every case it would move approptiately for example case KEY_UP: and it would move the coordinate up.
Also how would i access the arrow within the game without a if statement as this in an interactive tictactoe.
Last edited by xTonyLeo; 01-27-2013 at 01:40 AM.
What do you mean, "access the arrow"?
Just randomly, I think if I were implementing a tictactoe game I'd have keypresses of numbers map to the board like so:
I.e. like the numlock numbers.Code:7|8|9 -+-+- 4|5|6 -+-+- 1|2|3
I know that's not what you asked, but I don't really know what you asked!
So you're using KEY_UP, KEY_DOWN, etc to move the cursor for positioning the X or O. Somehow you must know what square they are in, so they don't go too far left. That is, if you start in the middle square, and they hit KEY_LEFT 17 times, you only move left once, since that is the edge of the board. Somehow your program must know that, must know which of the 9 possible squares they are in. You need to track that somehow if you aren't already. Each of those 9 positions maps to a (y, x) coordinate for your board. Say you start each turn in the middle square. That is position (y, x) = (1, 1) in your board. The user hits KEY_UP, so subtract one from the y coordinate. Now you are in the top-middle square, position (y, x) = (0, 1). The hit KEY_RIGHT, so add one to the x coordinate. Now they are in the top-right square, (y, x) = (0, 2). Make sure you don't go below 0 or above 2 for either y or x, no matter how many times they hit a given arrow key.
What it boils down to, is you must find a way to figure out the (y, x) for each square, and when the user puts an X or O in that square, and you draw it on the screen, you must also mark it in your board. I've already give you one suggestion, mapping screen coordinates. I've just given you a second suggestion, starting from a known position (middle square), calculate the new (y, x) coordinates after every key press. There are a multitude of ways to do this, you are free to pick any one of them, but you must pick one and start implementing it, otherwise, I can do nothing more to help you.
You find each square by knowing it's x and y coordinates, - that is absolutely correct. Using this logic, you MUST have this known.
The rest of what you need you get by simply using your cursor location function(s): ( in Windows: getConsoleCursorPosition(), in DOS or Windows using conio.h: wherex() and wherey() ).
So you have an exact layout or map, to every square. As the cursor is moved by pressing the arrow keys, you call your cursor location function(s). You COULD add and subtract the coordinates of the cursor by moving from a known position as suggested above - but you don't have to. The program can tell you this information, and with Tic-Tac-Toe, it's not a hit on the run-time. LOL!
I don't know whether the OP is using Windows or some other OS, but they did state they are using curses for screen manipulation, so the function they are looking for is getyx().