[c++] invalid types for array subscript

Discussion in 'Computer Programming, Emulation, and Game Modding' started by Nyap, Jun 12, 2016.

  1. Nyap
    OP

    Nyap HTML Noob

    Banned
    973
    344
    Jan 13, 2016
    That Chaos Site
    This is probably a really simple problem to fix and I'm stupid
    Code:
    #include <iostream>
    #include <cstdint>
    
    int g_difficulty;
    bool g_type;
    
    using std::cout;
    using std::cin;
    
    void setSlot(int16_t slot, int16_t &dataToSet)
    {
      switch (g_type)
      {
      case 0:
      dataToSet[slot-1]=1; break;
      case 1:
      dataToSet[slot-1]=2; break;
      }
    }
    
    void render(int16_t *gamedata)
    {
      for (int counter{}; counter<9; ++counter)
      {
      switch (gamedata[counter])
      {
      case 0:
      cout << " "; break;
      case 1:
      cout << "O"; break;
      case 2:
      cout << "X"; break;
      }
      switch (counter)
      {
      case 0:
      cout << "#"; break;
      case 1:
      cout << "#"; break;
      case 2:
      cout << "\n######\n"; break;
      case 3:
      cout << "#"; break;
      case 4:
      cout << "#"; break;
      case 5:
      cout << "\n######\n"; break;
      case 6:
      cout << "#"; break;
      case 7:
      cout << "#"; break;
      case 8:
      cout << "\n"; break;
      }
      }
    }
    
    int main()
    {
      int16_t gamedata[9]{};
      cout << "TicTacToe v0.5 by Nyap\n"
      << "====================\n"
      << "1) Easy\n"
      << "2) Medium\n"
      << "3) Hard\n";
    
      do
      {
      cout << "Please select a difficulty: ";
      cin >> g_difficulty;
      if (g_difficulty>0 && g_difficulty<4)
      {
      break;
      }
      cout << "Invalid input!\n";
      cin.clear(); cin.ignore(40000, '\n');
      }
      while (g_difficulty<1 || g_difficulty>3);
    
      cout << '\n';
    
      char type;
      do
      {
      cout << "Are you O or X?: ";
      cin >> type;
      if (type == 'X')
      {
      g_type=1; break;
      }
      if (type == 'O')
      {
      g_type=0; break;
      }
      cout << "Please enter 'O' or 'X' (make sure it's a capital letter)\n";
      cin.clear(); cin.ignore(40000, '\n');
      }
      while (!(type == 'O' || type == 'X'));
    
      cout << "====================\n"
      << "You need to enter a number from 1-9.\n"
      << "The top left of the grid is 1, the bottom right is 9.\n"
      << "To exit enter 0.\n"
      << "====================\n";
    
      render(gamedata);
    
      int16_t turn;
      while (0)
      {
      cout << "Your turn: "; cin >> turn;
      if (gamedata[turn]==0)
      {
      setSlot(turn, *gamedata);
      }
      }
      return 0;
    }
    I'm getting the problem in setSlot() but I included the rest of the code just in case
     
    Last edited by Nyap, Jun 12, 2016
  2. grossaffe

    grossaffe GBAtemp Addict

    Member
    2,765
    2,144
    May 5, 2013
    United States
    I only gave the code a brief glance-over, but I'd suggest that perhaps the function should be:
    Code:
    void setSlot(int16_t slot,int16_t *dataToSet)
    Also, when you call it, you're dereferencing gamedata when I believe what you want to do is pass in the address. Since it is an array, it is essentially a pointer already, so you can accomplish this a couple ways. The simplest:
    Code:
    setSlot(turn, gamedata);
    or:
    Code:
    setSlot(turn, &gamedata[0]);
     
    Nyap likes this.
  3. Nyap
    OP

    Nyap HTML Noob

    Banned
    973
    344
    Jan 13, 2016
    That Chaos Site
    I really need a refresher on the differences between a pointer and a reference :/
    but it works now thnx
     
  4. grossaffe

    grossaffe GBAtemp Addict

    Member
    2,765
    2,144
    May 5, 2013
    United States
    Yeah, it can be pretty confusing when you're getting started, but they become powerful tools once you fully understand them.

    It looks like your code isn't really making use of any C++ features outside of the iostreams and bools. Have you considered working with pure C?
     
  5. Nyap
    OP

    Nyap HTML Noob

    Banned
    973
    344
    Jan 13, 2016
    That Chaos Site
    I recently started learning about OOP (which is a feature only in C++) but I don't see how I could use what I've learn't so far in this program
    C is basically C++ with less features, I don't see any benefits in dumping C++
     
    Last edited by Nyap, Jun 12, 2016
  6. grossaffe

    grossaffe GBAtemp Addict

    Member
    2,765
    2,144
    May 5, 2013
    United States
    Right. Native OOP is the primary reason to make use of C++. C++ devs also tend to be big fans of STL and/or Boost, neither of which you're using in your program. It is, in fact, written procedurally, making it following more of a C paradigm.

    As an aside, you can write Object Oriented code in C, too. In fact, I have done just that in a game engine I started working on in my free time last summer. Why, you ask? I dunno, I guess I just wanted to see if I could.
    There are some fundamental differences in design decisions that go into coding in the two languages. Personally, I'm of a mind that it's good to fully understand C and how it works and it might lead to a better understanding of what's really happening when you use C++ and its features.
     
  7. Nyap
    OP

    Nyap HTML Noob

    Banned
    973
    344
    Jan 13, 2016
    That Chaos Site
    I'm going to take a break, but being the most complicated project i've made so far I thought it would be a good idea to add comments
    What do you think? Should I use more C style block comments, and if so, where?
    Code:
    #include <iostream>
    #include <cstdint>
    #include <cstdlib>
    
    int g_difficulty; //holds difficulty level (see main for more details)
    extern bool g_type; //holds players type (O or X)
    
    using std::cout;
    using std::cin;
    
    void setSlot(int16_t slot, int16_t *dataToSet)
    {
      switch (g_type) //Checks players type (O or X) and writes to gamedata accordingly
      {
      case 0:
      dataToSet[slot-1]=1; break;
      case 1:
      dataToSet[slot-1]=2; break;
      }
    }
    
    void render(int16_t *gamedata)
    {
      for (int counter{}; counter<9; ++counter) //Loops through all 9 slots
      {
      switch (gamedata[counter]) //Checks the slot and output is changed accordingly
      {
      case 0:
      cout << " "; break;
      case 1:
      cout << "O"; break;
      case 2:
      cout << "X"; break;
      }
      switch (counter) //Prints actual table
      {
      case 0:
      cout << "#"; break;
      case 1:
      cout << "#"; break;
      case 2:
      cout << "\n######\n"; break;
      case 3:
      cout << "#"; break;
      case 4:
      cout << "#"; break;
      case 5:
      cout << "\n######\n"; break;
      case 6:
      cout << "#"; break;
      case 7:
      cout << "#"; break;
      case 8:
      cout << "\n"; break;
      }
      }
    }
    
    int main()
    {
      int16_t gamedata[9]{};
      cout << "TicTacToe v0.5 by Nyap\n" //Title
      << "====================\n"
      << "1) Easy\n"
      << "2) Medium\n" //Difficulty information
      << "3) Hard\n";
    
      do
      {
      cout << "Please select a difficulty: ";
      cin >> g_difficulty; //Asks to enter difficulty
      if (g_difficulty>0 && g_difficulty<4)
      {
      break; //If the difficulty selected is valid, it will end the loop
      }
      cout << "Invalid input!\n"; //If the difficulty selected is invalid, it tells the user, refreshes cin and
      cin.clear(); cin.ignore(40000, '\n'); //it iterates again
      }
      while (g_difficulty<1 || g_difficulty>3);
    
      cout << '\n'; //Make a space between difficulty and type
    
      char type;
      do
      {
      cout << "Are you O or X?: ";
      cin >> type;
      if (type == 'X') //1 is X
      {
      g_type=1; break;
      }  //Converts input char to boolean and exits loop if input is valid
      if (type == 'O')
      {
      g_type=0; break; //0 is O
      }
      cout << "Please enter 'O' or 'X' (make sure it's a capital letter)\n";
      cin.clear(); cin.ignore(40000, '\n'); //Gives warning if input is invalid, refreshes cin and
      }
      while (!(type == 'O' || type == 'X')); //It iterates again
    
      cout << "====================\n"
      << "You need to enter a number from 1-9.\n"
      << "The top left of the grid is 1, the bottom right is 9.\n" //Outputs rules
      << "To exit enter 0.\n"
      << "====================\n";
    
      render(gamedata); //Renders the empty table
    
      int16_t turn; //Variable to hold slot that user wishes to modify
      while (1)
      {
      cout << "Your turn: "; cin >> turn; //Asks for what slot to modify
      if (turn>9 || turn<-1)
      {
      cout << "Invalid input!\n"; continue; //Checks if input is valid, and if not the user is notified and loop starts over
      }
      if (turn==0)
      {
      exit(0); //Quits the game if 0 is input
      }
      if (gamedata[turn-1]==0)
      {
      setSlot(turn, gamedata); //Sets the slot if all has gone well up to this point
      }
      else
      {
      cout << "That slot is already taken!\n"; continue; //If the slot is taken the player is notified and loop starts over
      }
      render(gamedata); //Table is rendered now that all changes have been made
      cout << "----------------\n"; //Prints a seperator
      aiTurn(gamedata); //Starts the bots turn! (bot.cpp)
      }
      return 0; //Returns 0 to operating system (won't be neccesary in most cases)
    }
     
  8. grossaffe

    grossaffe GBAtemp Addict

    Member
    2,765
    2,144
    May 5, 2013
    United States
    One thing I'll throw out there is that where I work, it is unacceptable to put a comment on the same line as code. It is also generally preferred to write a comment above a function to explain what it does. Perhaps something like this:
    Code:
    /*
    * Explain the function here
    *
    * @<arg1> is used for <X>
    * @<arg2> is used for <Y>
    *
    * @return <what the function returns>
    */
    
    unrelated to the issue of comments, I do have some notes on your code. Look at your switch(counter), for example. You have a bunch of cases which do the exact same thing. You can accomplish this with a lot fewer lines of code by utilizing the switch statement's fall-through property:
    Code:
    switch(counter)
    {
    case 0:
    case 1:
    case 3:
    case 4:
    case 6:
    case 7:
    cout <<"#";break;
    case 2:
    case 5:
    cout <<"\n######\n";break;
    case 8:
    cout <<"\n";break;}
    
    You could also make use of the default case for even more compact code and maybe a little more efficient. Technically it would make it print "#" even if, say, a 9 or 10 were passed in, but as you have it now, that's undefined behavior that I want to say would cause it to crash, and it's probably safe to assume it'll never get those values.
    Code:
    switch(counter)
    {
    case 2:
    case 5:
    cout <<"\n######\n";break;
    case 8:
    cout <<"\n";break;
    default:
    cout <<"#";break;
    }
    
    I would like to mention that I'm not too fond of the implementation of the setSlot() function. You really shouldn't do a switch statement on a bool, just use a good old fashion if-else statement with the bool as the conditional. Or, even better, I'd ditch the bool altogether. You could use an enum if you so desired for the player type and set that when you prompt the user if it wants to be X or O.
     
  9. Nyap
    OP

    Nyap HTML Noob

    Banned
    973
    344
    Jan 13, 2016
    That Chaos Site
    ok, I'll take all of this into consideration
    in my defence, this is the first time I've actually tried doing a project of my own, in the past it was just me quickly doing quiz questions from my tutorial
     
  10. grossaffe

    grossaffe GBAtemp Addict

    Member
    2,765
    2,144
    May 5, 2013
    United States
    I understand you're still a beginner. You'll (probably) pick up better coding practices along the way as you become more familiar with all the tools at your disposal. That's partially why I'd advocate working in C, as it has all the tools needed without overloading you with the issue of too many tools with too much bloat and too many different ways of doing things. Learn to use those tools really proficiently, and then you can start adding C++ features as necessary* to what you are trying to accomplish.

    *necessity being up to personal taste