C++ Array Help?

C++ Array Help?

Post by the0nlyb0ss on Tue Jan 04, 2011 1:15 am
([msg=51628]see C++ Array Help?[/msg])

Hey guys, haven't been on in a bit. I'm trying to make a game of Tic-Tac-Toe using SDL and C++, and I'm using an array to store the "board". It's a nine-slot array, a 0 means unoccupied, 1 means user-occupied, and 2 means AI-occupied. The problem is that the array doesn't get modified correctly when I call something like
Code: Select all
board[0] = 1;

The board gets modified in a really strange way. It'll change it to
1 1 1
1 0 0
1 0 0

Instead of
1 0 0
0 0 0
0 0 0

When it modifies other squares I sometimes get even weirder things, such as with square #9 (bottom-right), the array isn't modified at all! :shock:

I think it may have something to do with the way I'm passing it and modifying it in the header files? But I can't think of a solution...
main.cpp has the initial declaration that is
Code: Select all
#include "TicTacTie.h"
int board[9] = {
0, 0, 0,
0, 0, 0,
0, 0, 0};

board is passed to the function update(int* board), which is also in main.cpp
Which in turn passes it to the method move of the class user (declaration in TicTacToe.h and implementation in TicTacToe.cpp) like so:
Code: Select all
user.move(&display, squareNo, board, &logMessage);


The important part of the user.move method looks like this:
Code: Select all
void Player::move(Screen* display, int squareNo, int* board, std::string* logMessage)
{
    int x = 0, y = 0;
    if((board[squareNo - 1] != 0)){
        return;
    }
    // Other code omitted
    board[squareNo - 1] = 2;
    display->blit(display->screen, xOpt, x, y);
}


Can anyone explain why my board array isn't modified properly? :(
"Knowledge is knowing that a tomato is a fruit, but Wisdom is knowing not to put it in a fruit salad."
User avatar
the0nlyb0ss
Experienced User
Experienced User
 
Posts: 54
Joined: Thu Sep 02, 2010 11:24 pm
Location: California
Blog: View Blog (0)


Re: C++ Array Help?

Post by nathandelane on Tue Jan 04, 2011 1:59 pm
([msg=51670]see Re: C++ Array Help?[/msg])

So I tried out an idea based on what you're doing. I know it's not exactly the same code as you, but this code does what you expect it to and places the pieces in the correct slots in the array. So maybe you can give some more details on what you're doing and it'll help us help you.

Code: Select all
#include <algorithm>
#include <iostream>
#include <string>
#include <sstream>

/**
* Possible players.
*/
enum Player
{
   Human = 1,
   Computer
};

/**
* Board representation.
*/
class Board
{
public:
   static const unsigned int BOARD_SIZE = 9;

   Board();
   ~Board();
   void move(const Player player, const unsigned int squareIndex);
   void log(std::string message);
   void str();
private:
   unsigned int _board[Board::BOARD_SIZE];
};

/**
* Creates an instance of Board.
*/
Board::Board()
{
   std::fill_n(this->_board, Board::BOARD_SIZE, 0);
}

/**
* Destroys the current instance of Board.
*/
Board::~Board()
{
   std::fill_n(this->_board, Board::BOARD_SIZE, 0);
}

/**
* Places a move into a space on the board.
*/
void Board::move(const Player player, const unsigned int squareIndex)
{
   std::stringstream ss;

   ss << "Player " << player << " placed token on square " << (squareIndex + 1) << ".";

   log(ss.str());
   
   ss.str(std::string());

   if (squareIndex < Board::BOARD_SIZE)
   {
      if (this->_board[squareIndex] == 0)
      {
         this->_board[squareIndex] = player;
         
         str();
      }
      else
      {
         ss << "That square on the board is already occupied by " << this->_board[squareIndex] << ".";

         log(ss.str());
      }
   }
   else
   {
      ss << "The square you have chosen exceed the bounds of the board" << Board::BOARD_SIZE << ". You chose " << squareIndex << ".";

      log(ss.str());
   }
}

/**
* Writes a log message to stderr.
*/
void Board::log(std::string message)
{
   std::cerr << message << std::endl;
}

/**
* Prints string representation of this board.
*/
void Board::str()
{
   std::stringstream ss;

   for (int boardIndex = 0; boardIndex < Board::BOARD_SIZE; boardIndex++)
   {
      if (boardIndex > 0 && boardIndex < Board::BOARD_SIZE)
      {
         ss << ", ";
      }

      ss << this->_board[boardIndex];
   }

   log(ss.str());
}

void playGame()
{
   Board board;

   board.move(Human, 0);
   board.move(Computer, 3);
   board.move(Human, 3);
   board.move(Human, 4);
}

int main(int argc, char* argv[])
{
   playGame();

   return 0;
}
Me, Nathandelane, Highly influential to Hackerdom, Premature Optimization=http://c2.com/cgi/wiki?PrematureOptimization
User avatar
nathandelane
Poster
Poster
 
Posts: 204
Joined: Thu Jun 26, 2008 11:26 am
Location: Utah
Blog: View Blog (0)


Re: C++ Array Help?

Post by the0nlyb0ss on Tue Jan 04, 2011 7:02 pm
([msg=51687]see Re: C++ Array Help?[/msg])

Thanks for the quick reply :) I tried your example, and you're right, it does do what I originally intended to do!
If you'd like to check all of my code out it's here: (only about 350 lines of total code :P)
http://dl.dropbox.com/u/3701354/TicTacToe.zip

I just don't know if I'm passing my array properly to my instance methods and function. I noticed that you're using board as a class containing an array, but mine is just a global array variable... Also, yours is all in one file (technically), and mine is split into 3, and that is why I originally thought there was a problem... Do you think that I should go and create a Board class like you did and see if it would work, instead of keeping it a global variable?

An off-topic question about your code, I've never seen this before:
Code: Select all
std::fill_n(this->_board, Board::BOARD_SIZE, 0);

What does that do?
"Knowledge is knowing that a tomato is a fruit, but Wisdom is knowing not to put it in a fruit salad."
User avatar
the0nlyb0ss
Experienced User
Experienced User
 
Posts: 54
Joined: Thu Sep 02, 2010 11:24 pm
Location: California
Blog: View Blog (0)


Re: C++ Array Help?

Post by nathandelane on Wed Jan 05, 2011 12:37 am
([msg=51707]see Re: C++ Array Help?[/msg])

the0nlyb0ss wrote:Thanks for the quick reply :)

An off-topic question about your code, I've never seen this before:
Code: Select all
std::fill_n(this->_board, Board::BOARD_SIZE, 0);

What does that do?


You're welcome. And to answer your question. std::fill_n is a function defined in <algorithm>. What it does is fill a collection, in this case a simple array of int. It probably is not required to fill an array of int with zeros, because the default value for an int on most systems is zero, but it could also be undefined. This is probably a little superstitious, but that's what it does. The definition for it is

Code: Select all
template < class OutputIterator, class Size, class T >
  void fill_n ( OutputIterator first, Size n, const T& value );

Here is a link to the definition: http://www.cplusplus.com/reference/algorithm/fill_n/

I am looking at your code right now to understand what is going on better.
Me, Nathandelane, Highly influential to Hackerdom, Premature Optimization=http://c2.com/cgi/wiki?PrematureOptimization
User avatar
nathandelane
Poster
Poster
 
Posts: 204
Joined: Thu Jun 26, 2008 11:26 am
Location: Utah
Blog: View Blog (0)


Re: C++ Array Help?

Post by the0nlyb0ss on Wed Jan 05, 2011 1:03 am
([msg=51714]see Re: C++ Array Help?[/msg])

nathandelane wrote:What it does is fill a collection, in this case a simple array of int.

Really interesting! Sort of just like a for loop to fill the array, but it can be used for any container?

Sorry the code is pretty messy and not very well documented!
The main functions/methods that have to do with the board array are
Code: Select all
update(int* board);

Code: Select all
Player::move(Screen* display, int squareNo, int* board, std::string* logMessage);

and
Code: Select all
AI::move(Screen* display, int* board);
"Knowledge is knowing that a tomato is a fruit, but Wisdom is knowing not to put it in a fruit salad."
User avatar
the0nlyb0ss
Experienced User
Experienced User
 
Posts: 54
Joined: Thu Sep 02, 2010 11:24 pm
Location: California
Blog: View Blog (0)


Re: C++ Array Help?

Post by nathandelane on Wed Jan 05, 2011 11:55 am
([msg=51731]see Re: C++ Array Help?[/msg])

Yes, basically std::fill_n is like a for loop. It can be used with any collection that is iterable, which if it's a C++ collection it is. The definition requires something that falls into the type "OutputIterator". OutputIterator is more specialized than just an array or collection, like vector<&T>. Collections usually have iterators or can be wrapped in an iterator in order to iterate over the collection.

On that page I linked you to for the definition of std::fill_n it states that the following is the defined behavior for the function:

Code: Select all
template < class OutputIterator, class Size, class T >
  void fill_n ( OutputIterator first, Size n, const T& value )
{
  for (; n>0; --n)  *first++ = value;
}

Anyway that's probably why it requires the number of items to fill.

I was working on a more complete version of the text-mode TicTacToe based on your idea. You mentioned that I had just used one file, which does simplify the program significantly. Once you start using header files then the whole solution becomes more complex, but it is also easier to maintain. Here is a link to my version of TicTacToe so far, which is closer to what you're looking for. The only thing missing right now is the function that determines a winner: http://dl.dropbox.com/u/10646479/TicTacToe.zip

I'm still looking at your code, because everything I've read says it should work. I haven't tried to run it yet though.

-- Wed Jan 05, 2011 10:15 am --

Alright I just wrote a simple program to test passing an array of ints around and manipulating it.

Code: Select all
#include <iostream>

int intArray[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};

void printArray(int * array, int size)
{
   for (int arrayIndex = 0; arrayIndex < size; arrayIndex++)
   {
      if (arrayIndex > 0)
      {
         std::cout << ", ";
      }

      std::cout << array[arrayIndex];
   }

   std::cout << std::endl;
}

void manipulateArray(int * intArray)
{
   intArray[1] = 1;
   intArray[3] = 1;
   intArray[5] = 1;
   intArray[7] = 1;
}

int main(int argc, char * argv[])
{
   printArray(intArray, 9);

   intArray[0] = 24;

   printArray(intArray, 9);

   manipulateArray(intArray);

   printArray(intArray, 9);
}

This program's output looks like:

Code: Select all
0, 0, 0, 0, 0, 0, 0, 0, 0
24, 0, 0, 0, 0, 0, 0, 0, 0
24, 1, 0, 1, 0, 1, 0, 1, 0

Which is what I would expect. And I thought that was basically what you are doing. So I need to look at your code some more.

-- Wed Jan 05, 2011 2:24 pm --

BTW I finished up the text mode Tic Tac Toe game (Same Dropbox URL as before): http://dl.dropbox.com/u/10646479/TicTacToe.zip
Me, Nathandelane, Highly influential to Hackerdom, Premature Optimization=http://c2.com/cgi/wiki?PrematureOptimization
User avatar
nathandelane
Poster
Poster
 
Posts: 204
Joined: Thu Jun 26, 2008 11:26 am
Location: Utah
Blog: View Blog (0)


Re: C++ Array Help?

Post by the0nlyb0ss on Wed Jan 05, 2011 7:32 pm
([msg=51763]see Re: C++ Array Help?[/msg])

If you want the binaries with all of the data, it's here:
http://dl.dropbox.com/u/3701354/TicTacToe%20Binaries.zip
After running the program, check the bottom of the ErrorLog.log file for
an outline of the array and its positions.

Your code seems to have an issue with linking on my computer :/
Code: Select all
C:\Users\the0nlyb0ss\Downloads\TicTacToe\TicTacToe>g++ -o tictactoe.exe -Xlinker --enable-auto-import main.cpp Board.h Board.cpp Game.h Game.cpp
C:\Users\George\AppData\Local\Temp\ccbQyq39.o:Board.cpp:(.text+0x8e1): undefined reference to `Nathandelane::WinningMoves::WINNING_MOVES'
C:\Users\George\AppData\Local\Temp\ccbQyq39.o:Board.cpp:(.text+0x8fc): undefined reference to `Nathandelane::WinningMoves::WINNING_MOVES'
C:\Users\George\AppData\Local\Temp\ccbQyq39.o:Board.cpp:(.text+0x918): undefined reference to `Nathandelane::WinningMoves::WINNING_MOVES'
collect2: ld returned 1 exit status

I'm trying to change up my code into using a Board class now and see if it works and at the same time forcing myself to learn to std::fill method ;)

Also, should I change all of my classes to use this-> wherever it is applicable? I'm used to Python where you HAVE to put self as the first arg, but in C++ is seems optional?

-----------------------------------------------------------------------------------------------

After implementing a Board class, result is still the same :(
New source code and binaries are here:
http://dl.dropbox.com/u/3701354/TicTacToe.zip
Last edited by the0nlyb0ss on Wed Jan 05, 2011 7:58 pm, edited 1 time in total.
"Knowledge is knowing that a tomato is a fruit, but Wisdom is knowing not to put it in a fruit salad."
User avatar
the0nlyb0ss
Experienced User
Experienced User
 
Posts: 54
Joined: Thu Sep 02, 2010 11:24 pm
Location: California
Blog: View Blog (0)


Re: C++ Array Help?

Post by nathandelane on Wed Jan 05, 2011 7:56 pm
([msg=51766]see Re: C++ Array Help?[/msg])

the0nlyb0ss wrote:
Code: Select all
C:\Users\the0nlyb0ss\Downloads\TicTacToe\TicTacToe>g++ -o tictactoe.exe -Xlinker --enable-auto-import main.cpp Board.h Board.cpp Game.h Game.cpp
C:\Users\George\AppData\Local\Temp\ccbQyq39.o:Board.cpp:(.text+0x8e1): undefined reference to `Nathandelane::WinningMoves::WINNING_MOVES'
C:\Users\George\AppData\Local\Temp\ccbQyq39.o:Board.cpp:(.text+0x8fc): undefined reference to `Nathandelane::WinningMoves::WINNING_MOVES'
C:\Users\George\AppData\Local\Temp\ccbQyq39.o:Board.cpp:(.text+0x918): undefined reference to `Nathandelane::WinningMoves::WINNING_MOVES'
collect2: ld returned 1 exit status


Yes that is because the g++ command you issued there doesn't include WinningMoves.h and WinningMoves.cpp. So instead just do:

Code: Select all
C:\~> g++ -o tictactoe.exe *.h *.cpp


The this-> is not a requirement in C++. It can make semantics more obvious when you look back at your code. I use syntactic hinting in my code a lot so that I immediately understand the scope, which in turn makes the program easier to follow and maintain. If you download the program again, you will see that I took out the this-> in all of the files.

In your case I don't think that creating a Board class will necessarily solve all of your problems. I started and finished my program in text mode because it simplifies all of the overhead and complexity that SDL adds. If I wanted to I could relatively enhance the program now by adding SDL. In general separating control, models, and display (or view) makes all programs much easier to maintain and debug. Perhaps a rewrite would do you some good. Take some time and see what I did -- you definitely DON'T need to copy or even use my code -- and form a plan based on what objects you want and how you want them to interact. If you want your board to be global and utilize C++ OOP (classes) then I think you should probably put the board into a singleton class. This is how OOP handles "global variables". In my code I thought that allowing the board to control all changes to itself made sense: a player may ask the board to place a marker, but the board can decline the request if another marker is already in the spot in question. That's my Object-Oriented mind thinking.

In general OOP takes a lot of practice, more practice than simply programming. Try a few different things, use what works best. Over a year ago I wrote an article about this called Two or Three Ways to Do Things.
Me, Nathandelane, Highly influential to Hackerdom, Premature Optimization=http://c2.com/cgi/wiki?PrematureOptimization
User avatar
nathandelane
Poster
Poster
 
Posts: 204
Joined: Thu Jun 26, 2008 11:26 am
Location: Utah
Blog: View Blog (0)


Re: C++ Array Help?

Post by the0nlyb0ss on Wed Jan 05, 2011 8:24 pm
([msg=51769]see Re: C++ Array Help?[/msg])

:oops: What a silly mistake, I really should have realized that...
Ran it, works perfectly!

I see what you mean about this-> That seems like a good idea to distinguish variables, I just did it and it makes the code much more readable than I thought it would! Plus it'll keep me close to Python's self ;)

I'm using SDL because I want it as a beginning introduction to game design, but maybe I should make a text-based Tic-Tac-Toe, that would give me a really good idea of the design for the graphical version!

After that, I think I'll do a complete rewrite from scratch, definitely redesigning my OOP structure, maybe learning some more SDL and C++ on the way. I think I'll try a few different strategies, no OOP, some OOP, and full OOP and see how each one goes. I may be back within a week with a remade design!

By the way, I really like your blog! I've already read a few articles and realized that I'm not the only one who can't get it on the first try ;)

Anyway, thanks a ton for your help! At first I thought it was just a silly mistake that I had made, but I guess my entire design was flawed, oh well, not bad for a first try :D

Thanks again!
"Knowledge is knowing that a tomato is a fruit, but Wisdom is knowing not to put it in a fruit salad."
User avatar
the0nlyb0ss
Experienced User
Experienced User
 
Posts: 54
Joined: Thu Sep 02, 2010 11:24 pm
Location: California
Blog: View Blog (0)


Re: C++ Array Help?

Post by nathandelane on Thu Jan 06, 2011 11:05 am
([msg=51791]see Re: C++ Array Help?[/msg])

Nah don't worry about it. Anyway I'm glad I could help you out somewhat, even though I still can't find the problem of what's going wrong exactly. Thanks about my blog. I don't have much on there, because I don't have much time. But the things I write are things that are important to me, and that I feel would be helpful to some other people.

As far as using SDL goes, I didn't mean to sound like that was a bad thing to use it. My intent (which I realize was not clear at all) was to say that in my code I tried to reduce the coupling between my user interface and all of the other functionality. In general this should be a goal no matter if your program is functional or object-oriented in nature. In my code Board contains most of the game's functionality, WinningMoves contains some important data (to determine if there is a winner), and Game is where I house my game loop and input control. In my case [I meant] all that I would need to do to make the game use SDL is swap out Game.h and Game.cpp for one that uses SDL instead of the CLI. Keeping data structures and behavior separate from the user interface is what makes a better program that is easier to maintain and extend, and this takes practice. I talk more about practice and some other things in a couple of other posts on this forum in Programming called "Who Wants to Learn How to Program?" (one is sticky at the top, and the other is somewhere in the middle, but most of it is in the sticky one): sticky Who Wants to Learn How to Program and other Who Wants to Learn How to Program (extension).

Good luck on your project.
Me, Nathandelane, Highly influential to Hackerdom, Premature Optimization=http://c2.com/cgi/wiki?PrematureOptimization
User avatar
nathandelane
Poster
Poster
 
Posts: 204
Joined: Thu Jun 26, 2008 11:26 am
Location: Utah
Blog: View Blog (0)


Next

Return to C and C++

Who is online

Users browsing this forum: No registered users and 0 guests

cron