Our assignment was to write a tic-tac-toe program for my programming class.
It is person vs. computer and the computer makes "random" moves, even if computer is going to lose they will choose a random place to put their x or o
it is all correct, now what I have to do is modify the program so the computer plays "smart", and by smart i mean blocking the player from making a 3 of a kind, etc.
so I have no idea how to do that

here is my program now:

#include <iostream>

using namespace std;

void clearBoard(int board[]);
void drawBoard(int board[]);
int getPlayerMove(int player);
int makeRandMove(int player);
bool isMoveValid(int boardp[], int move);
bool isaWin(int board[], int move);
const int board_size = 9;

int main()
{
  int board[board_size];
  int turn = 0;
  int move = 10;

  srand(time(0));

  clearBoard(board);

  while(!isaWin(board, move)){
    drawBoard(board);
    if(2 == turn)
      turn = 1;
    else
      turn = 2;

    do {
      if(2 == turn)
	move = getPlayerMove(turn);
      else
	move = makeRandMove(turn);
    } while(!isMoveValid(board, move));

    board[move] = turn;
  }

  drawBoard(board);
  cout << "Player " << turn << " wins." << endl;

  return 0;
}

void clearBoard(int board[])
{
  int i;

  for(i = 0; i < board_size; ++i) {
    board[i] = -i - 1;
  }
}

void drawBoard(int board[])
{
  int i, j;

  for(i = 0; i <= 6; i = i+3) {
    for(j = 0; j < 3; ++j) {
      if(board[i + j] == 2)
	cout << "X";
      else if(board[i + j] == 1)
	cout << "O";
      else
	cout << "_";
    }
    cout << endl;
  }
}

int getPlayerMove(int player)
{
  int move;

  cout << "Player " << player << " enter move: ";
  cin >> move;
  return move;
}

int makeRandMove(int player)
{
  cout << "Computer (player " << player << ") moving." << endl;
  return rand() % board_size;
}

bool isMoveValid(int board[], int move)
{
  if(board[move] < 0)
    return true;
  return false;
}

bool isaWin(int board[], int move)
{
  if((board[0] == board[1] && board[0] == board[2]) ||
     (board[3] == board[4] && board[3] == board[5]) ||
     (board[6] == board[7] && board[6] == board[8]) ||
     (board[0] == board[3] && board[0] == board[6]) ||
     (board[1] == board[4] && board[1] == board[7]) ||
     (board[2] == board[5] && board[2] == board[8]) ||
     (board[0] == board[4] && board[0] == board[8]) ||
     (board[2] == board[4] && board[2] == board[6]))
    return true;
  return false;
}

Dani AI

Generated

Nice start. To make the computer play "smart" without going full minimax, add a small rule-based move picker. In priority order: (1) take a winning move if available, (2) otherwise block the human's winning move (what suggested), (3) take center if free, (4) take a corner (as noted, corners and center are strongest), then (5) take a side. This is fast, easy to read, and will both win and block obvious threats.

Drop-in helper and move chooser (works with your board encoding where empty squares are negative):

// Return index [0..8] that completes a line for 'who', or -1 if none.
int lineToComplete(int b[], int who) {
  static const int L[8][3] = {
    {0,1,2},{3,4,5},{6,7,8},
    {0,3,6},{1,4,7},{2,5,8},
    {0,4,8},{2,4,6}
  };
  for (int i = 0; i < 8; ++i) {
    int a=L[i][0], c=L[i][1], d=L[i][2];
    int cnt = (b[a]==who) + (b[c]==who) + (b[d]==who);
    int empty = (b[a]<0? a : (b[c]<0? c : (b[d]<0? d : -1)));
    if (cnt==2 && empty!=-1) return empty; // win or block
  }
  return -1;
}

int chooseSmartMove(int b[], int me, int opp) {
  int m = lineToComplete(b, me);  if (m!=-1) return m;   // try to win
  m = lineToComplete(b, opp);     if (m!=-1) return m;   // block player
  if (b[4] < 0) return 4;                                   // center
  static const int corners[4] = {0,2,6,8};
  for (int i=0;i<4;++i) if (b[corners[i]] < 0) return corners[i];
  static const int sides[4] = {1,3,5,7};
  for (int i=0;i<4;++i) if (b[sides[i]] < 0) return sides[i];
  for (int i=0;i<9;++i) if (b[i] < 0) return i;            // fallback
  return 0; // board full (should not be reached if you check for ties)
}

Use it where the computer moves, e.g. replace makeRandMove(turn) with chooseSmartMove(board, /*me*/ 1, /*opp*/ 2). Also harden isMoveValid to check bounds: return move >= 0 && move < board_size && board[move] < 0;. If you later want perfect play, swap chooseSmartMove for a small minimax, but this heuristic will already feel much smarter.

Recommended Answers

All 3 Replies

I'd probably have an integer function called:

int PlayerHasWinningMove (int board[]);

This function would test to see whether any move by the human opponent could win the game. It would return some number that is not 0 through 8 (i.e. -1) if there was no winning move that the player could make to win, and it would return some number from 0 to 8 if the player COULD make a winning move. The 0 through 8 return value would be the square representing the winning move. Call that function. If it returns -1, then call the makeRandMove function. If it returns something that is 0 through 8, don't call makeRandMove. Instead, have the computer's move be the return value from "PlayerHasWinningMove". That will block the player's move before he/she can make it.

If you want to make a winning code you should firstly ofcourse win ,but mostimportantly block the computer like in the case in the computer can get a row or a column or a diagnol in the next move you should block it.
like in the case
[o][o][ ]
[o][x][x]
[ ][ ][x]
so in the next move the computer can get two ways of winning so try getting the corners and the centers.Remmember a smart program should win but not at the cost of blockiong your opponent.Make your code in that way

can you make this tic tac toe game using c++ window form ?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.