Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am pretty new in C++ programming. I am coding for Tic Tac Toe game to understand how its algorithm works. My question is about I have two functions. One of them is clearBoard function and the other one is drawBoard function. I got little help about them but I couldnt figure it out the way those functions works. Can anyone simply explain me what is exactly what? I have been trying to solve it and understand it but I think I got more confused. It might be a piece of cake but I really want to understand what's exactly going on. Thanks for your time and attention...
Here clearBoard function:
void clearBoard(int board[])
{
int i;
for(i = 0; i < board_size; i++) {
board[i] = -i - 1;
}
}
And here is my drawBoard function.
void drawBoard(int board[])
{
int i, j;
int n = 0;
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 << "|" << n << "|";
n = n+1;
}
cout << endl;
}
}
This is my main.cpp file. I just wanted to post my entire work at least it will be easier to see complete picture.
#include <iostream>
#include <ctime>
#include<cstdlib>
#include "Define.h"
using namespace std;
int main()
{
int board[board_size];
int turn = 0;
int p = 0;
int move = 10;
srand(time(NULL));
clearBoard(board);
cout << "This turn is randomly chosen!" << endl;
p = random(2) + 1;
cout << "The first move goes to Player: " << p << endl;
turn = p;
do {
if(p== 2 && 2 == turn)
{
drawBoard(board);
move = getPlayerMove(turn);
}
else
move = makeRandMove(turn);
} while(!isMoveValid(board, move));
board[move] = turn;
while(!isWin(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;
}
And this is the functions.cpp file that has the functions that I was talking about above.
#include <iostream>
#include<cstdlib>
using namespace std;
const int board_size = 9;
void clearBoard(int board[])
{
int i;
for(i = 0; i < board_size; i++) {
board[i] = -i - 1;
}
}
int random(int x)
{
return rand() % x;
}
void drawBoard(int board[])
{
int i, j;
int n = 0;
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 << "|" << n << "|";
n = n+1;
}
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 isWin(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;
}
And here is my define.h header file has all the protypes...
#ifndef formula
#define formula
const int board_size = 9;
int random(int x);
void clearBoard(int board[]);
void drawBoard(int board[]);
int getPlayerMove(int player);
int makeRandMove(int player);
bool isMoveValid(int boardp[], int move);
bool isWin(int board[], int move);
#endif
The key to understanding the two board functions you are having difficulty with, clearBoard and drawBoard, you need to understand the data structure that you're storing your game board in. This is, in fact, a pretty simple example. Your board is defined as an array of 9 items:
int board[board_size];
...
const int board_size = 9;
The best way to think about this is if you take your 3 x 3 tic-tac-toe game board, and lay each row side by side. So the first three elements are the first row, the next three are the second row, and the last three are the final row.
The drawBoard function is the more complex of the two functions, but if you understand what the array is and what it represents, it makes this function much more understandable. The outer for loop is looping through each "row" of the gameboard, while the inner for loop loops through each element in that row.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
A few time ago I made a game similar to Gomoku in C++ that is taking between two players.
Now I want to make it Player vs Computer.
I tried to do it in simplest way, by making a function of computer to pick a random cell but I still haven't succeeded.
I understood that in order of getting a random number I can use rand() and for a letter something like this:
char letters[] = "abcdefghijklmnopqrstuvwxyz";
char x = letters[rand() % 26];
Can someone help me and describe how to implement a computer player?
This is my implementation so far:
#include <iostream>
#include <iomanip>
using namespace std;
void print_table(int x[][15]) {
system("cls");
for (int i = 0; i < 15; i++) {//the loop that use to print out the english character row
if (i == 0)
cout << setw(4) << "A";
else if (i == 1)
cout << " B";
else if (i == 2)
cout << " C";
else if (i == 3)
cout << " D";
else if (i == 4)
cout << " E";
else if (i == 5)
cout << " F";
else if (i == 6)
cout << " G";
else if (i == 7)
cout << " H";
else if (i == 8)
cout << " I";
else if (i == 9)
cout << " J";
else if (i == 10)
cout << " K";
else if (i == 11)
cout << " L";
else if (i == 12)
cout << " M";
else if (i == 13)
cout << " N";
else if (i == 14)
cout << " O";
else if (i == 15)
cout << " P";
}
cout << endl;
for (int i = 0; i < 15; i++) {
cout << setw(2) << i;//print out the row number
for (int j = 0; j < 15; j++) {//print out the board game.
if (x[i][j] == 0) {//the inital value is 0, so when the block is 0 then print out the '.'
cout << " .";
}
else if (x[i][j] == 1) {//when the player O input the block then the value will adding one then if check the block is one then output the 'o'
cout << " O";
}
else if (x[i][j] == 2) {//when the player X input the block then the value will adding two then if check the block is two then output the 'x'
cout << " X";
}
}
cout << endl;
}
}
int check_player(int p) {
if (p == 1) {//change the player everytime before the next loop compile
p++;
}
else {
p--;
}
return p;
}
void input_value(int &t, int &n, int p, int x[][15]) {
char eng;
int number;
do {//the loop that ask for the user input the location.
cout << "player ";
if (p == 1) {
cout << "O";
}
else {
cout << "X";
}
cout << ", make a move: ";
cin >> eng;//input the location
cin >> number;
if (eng == 'A')//change the character to different number
t = 0;
else if (eng == 'B')
t = 1;
else if (eng == 'C')
t = 2;
else if (eng == 'D')
t = 3;
else if (eng == 'E')
t = 4;
else if (eng == 'F')
t = 5;
else if (eng == 'G')
t = 6;
else if (eng == 'H')
t = 7;
else if (eng == 'I')
t = 8;
else if (eng == 'J')
t = 9;
else if (eng == 'K')
t = 10;
else if (eng == 'L')
t = 11;
else if (eng == 'M')
t = 12;
else if (eng == 'N')
t = 13;
else if (eng == 'O')
t = 14;
if (!(eng >= 'A'&&eng <= 'M') || !(number >= 0 && number <= 14) || x[number][t] != 0) {//when the input wrong, output the statement to ask anouther input and loop again.
cout << "Invaid input, Try again!" << endl;
continue;
}
else {//if no problem then this input loop is break and jump to the next statement
break;
}
} while (1);//Because it will break as well so the do-while loop is no any requirement
n = number;
}
int main() {
const int num = 15;//the number for constant the array row and column value
char check_e;//for the user input the column
int R[num][num] = { 0 }, check_n, player = 1, buger = 0, transfer, playerO_win = 0, playerX_win = 0, draw = 0, check_draw;//the variable that for user input or checking the game statment
do {//launch the loop for the user input again and again
check_draw = 0;//reset the checking of draw
print_table(R);
input_value(transfer, check_n, player, R);
R[check_n][transfer] += player;//change the value according the player's input and the player name.
for (int i = 0; i < num; i++) {
for (int j = 0; j < num; j++) {
if (i <= 8 && R[j][i] != 0 && (R[j][i] == R[j][i + 1] && R[j][i] == R[j][i + +2] && R[j][i] == R[j][i + 3] && R[j][i] == R[j][i + 4])) {//the checking for the row bingo
if (R[j][i] == 1) {
playerO_win++;
break;
}
else {
playerX_win++;
break;
}
}
else if (j <= 8 && R[j][i] != 0 && (R[j][i] == R[j + 1][i] && R[j][i] == R[j + 2][i] && R[j][i] == R[j + 3][i] && R[j][i] == R[j + 4][i])) {//the checking for the column bingo
if (R[j][i] == 1) {
playerO_win++;
break;
}
else {
playerX_win++;
break;
}
}
else if (j <= 8 && i <= 8 && R[j][i] != 0 && (R[j][i] == R[j + 1][i + 1] && R[j][i] == R[j + 2][i + 2] && R[j][i] == R[j + 3][i + 3] && R[j][i] == R[j + 4][i + 4])) {//the checking for the \ situation.
if (R[j][i] == 1) {
playerO_win++;
break;
}
else {
playerX_win++;
break;
}
}
else if ((j >= 4 || i >= 4 || i <= 8) && R[j][i] != 0 && (R[j][i] == R[j - 1][i + 1] && R[j][i] == R[j - 2][i + 2] && R[j][i] == R[j - 3][i + 3] && R[j][i] == R[j - 4][i + 4])) {//the checking for the / situation
if (R[j][i] == 1) {
playerO_win++;
break;
}
else {
playerX_win++;
break;
}
}
for (int i = 0; i < num; i++) {//the loop for checking the draw
for (int j = 0; j < num; j++) {//this loop will check for every time compilation.
if (R[j][i] == 0)//when there are any empty block then the check_draw will adding, the draw situation is the check_draw be 0
check_draw++;
}
}
if (check_draw == 0) {//when the check_draw equal to 0 which mean the situation is no empty block
draw++;
break;
}
}
if (playerO_win != 0 || playerX_win != 0 || draw == 1)//break the second loop
break;
}
if (playerO_win == 1 && playerX_win == 0) {// when the player win print the block game again and print out the win statement
print_table(R);
cout << "player O wins!" << endl;
break;
}
else if (playerX_win == 1 && playerO_win == 0) {//the other player win the game
print_table(R);
cout << "player X wins!" << endl;
break;
}
else if (draw == 1) {//the draw block game print
print_table(R);
cout << "Draw game!" << endl;
break;
}
player = check_player(player);
} while (1);//in fact it is no need for the loop statement, because most of the situation will have a break statement for out of the loop
return 0;
}
Here's how I would implement it probably based on your initial implementation:
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
#define SIZE 10
#define LINE_LENGTH 4
#define COMPUTER_O_PLAYER true
#define COMPUTER_X_PLAYER false
void print_board(unsigned char x[SIZE][SIZE]) {
cout << " ";
for (int i = 0; i < SIZE; i++) { // The loop that use to print out the english character row.
cout << (char) ('A' + i) << " ";
}
cout << endl;
for (int i = 0; i < SIZE; i++) {
cout << setw(2) << i; // Print out the row number.
for (int j = 0; j < SIZE; j++) {//print out the board game.
if (x[i][j] == 0) { // Unoccupied tile.
cout << " .";
} else if (x[i][j] == 1) { // The tile belongs to X.
cout << " X";
} else { // The tile belongs to O.
cout << " O";
}
}
cout << endl;
}
}
void get_position(int &x, int &y, bool player, unsigned char board[SIZE][SIZE]) {
char eng;
// The loop that ask for the user input the location.
do {
cout << "Player " << (player ? "X" : "O") << ", make a move: ";
cin >> eng;
y = toupper(eng) - 'A';
cin >> x;
if (!(x >= 0 && x < SIZE) || !(y >= 0 && y < SIZE) || board[x][y] != 0) {
// When the input wrong, output the statement to ask another input and loop again.
cout << "Invalid input, Try again!" << endl;
continue;
} else { // If no problem then this input loop is break and jump to the next statement.
break;
}
} while (true);
}
void get_random_position(int &x, int &y, bool player, unsigned char board[SIZE][SIZE]) {
do {
x = rand() % SIZE;
y = rand() % SIZE;
} while ((!(x >= 0 && x < SIZE) || !(y >= 0 && y < SIZE) || board[x][y] != 0));
cout << "Player " << (player ? "X" : "O") << " chose: " << (char) ('A' + y) << x << endl;
}
unsigned int
count_in_direction(unsigned char board[SIZE][SIZE], unsigned int x, unsigned int y, short int m_x, short int m_y) {
unsigned int count = 0;
unsigned char tile = board[x][y];
while (((x + m_x >= 0) && (x + m_x < SIZE)) && ((y + m_y >= 0) && (y + m_y < SIZE)) &&
(board[x + m_x][y + m_y] == tile)) {
x += m_x;
y += m_y;
count++;
}
return count;
}
bool full_line(unsigned char board[SIZE][SIZE], unsigned int x, unsigned int y) {
const short int directions[4][2] = {{1, 0},
{1, -1},
{0, 1},
{1, 1}};
for (const auto &direction : directions) {
if (LINE_LENGTH - 1 <= (count_in_direction(board, x, y, direction[0], direction[1]) +
count_in_direction(board, x, y, -direction[0], -direction[1])))
return true;
}
return false;
}
int main() {
// The variable that for user input or checking the game state.
unsigned char board[SIZE][SIZE] = {0};
int x, y;
bool player = true;
bool draw;
srand(time(nullptr));
// Run the game.
do {
print_board(board);
if ((player && COMPUTER_X_PLAYER) || (!player && COMPUTER_O_PLAYER)) {
get_random_position(x, y, player, board);
} else {
get_position(x, y, player, board);
}
board[x][y] = player ? 1 : 2;
if (full_line(board, x, y)) {
print_board(board);
cout << "player " << (player ? "X" : "O") << " wins!" << endl;
break;
}
draw = true;
for (int k = 0; (k < SIZE) && draw; k++) {
for (int l = 0; (l < SIZE) && draw; l++) {
if (board[k][l] == 0) draw = false;
}
}
if (draw) {
print_board(board);
cout << "Draw game!" << endl;
break;
}
player = !player;
} while (true);
return 0;
}
Please take a deep look in this implementation and internalize its approach, it also support both players as user, user and computer, and both computer.
Some insights:
Don't use long if ... else when there are simpler ways.
Use the correct data types for variables.
Use indicative variables naming.
Use loops where possible, again, not long if ... else.
Keep the code well formatted.
Use #define to define global constants to use, for easier changes later and readability.
You can indeed use rand, but you don't need to get a character, you can get an index straight away and avoid the conversion.
I just started a CS degree and I'm brand new to actual programming and hence the implementation is proving difficult. I recently had an assignment that left me stumped. I was stumped because I was unable to link all the files together (2 header files .hpp and 2 implementation files .cpp). The assignment has come and gone I'm just curious as to how I would link all the files together since I know that when it comes to compile time the Board.hpp and Board.cpp files will compile into one file and the TicTacToe.hpp and TicTacToe.cpp files will compile into one file AND then all of the two compiled files will be linked to each other to produce the executable file.
Here is the error I get when I try to compile in g++:
TicTacToe.hpp:1:9: warning: #pragma once in main file
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
I have no idea what any of that means.
I'll post the files below for your reviewing. I appreciate any help you can give. Again, I'm brand new at this so if you could explain things simply I would really appreciate it.
Board.hpp
#ifndef BOARD_HPP
#define BOARD_HPP
#include <iostream>
#include <string>
class TTTBoard
{
private:
char Board[3][3]; //creates array
int play(); // prototype for play function
void makeMove(); //prototype for makeMove function
int turn(int); //prototype for turn function
int check(int, int); //prototypr for check function
void print(char x[][3]); //prototype for print function
int gameState(char x[][3]); //prototype for gameState fuction
int player1, player2, draw, player, winner, done; //creates variables to be used.
int row, col; //creates variables to be used in gamestate function
public:
int TtlGames, TtlP1, TtlP2, TtlDraws; //creates variables that will define gamestate
void intBoard(); //prototype for intboard
};
#endif
The next one is kind of long.
Board.cpp
#include "Board.hpp"
#include <iostream>
#include <iomanip>
void TTTBoard::intBoard() //function to initialize the board
{ //initialzes the variables in order
done = false; // to be used for later functions
winner = 0;
player = 2;
player1 = 1;
player2 = 2;
draw = 3;
int i, k;
for (k = 0; k<3; k++) //initializes array to 0
{
for (i = 0; i<3; i++)
{
Board[k][i] = 0;
}
}
play(); //begins the game
}
int TTTBoard::check(int row, int col) //checks if spot if occupied
{
if (Board[row][col] == 0)
{
return true;
}
else if (Board[row][col] != 0)
{
std::cout << "That square is already taken.";
return false;
}
else
{
std::cout << "Checking for win.";
gameState(Board);
}
return false;
}
void TTTBoard::makeMove() //records players move
{
player = turn(player);
int answer = false;
while (answer == false)
{
std::cout << "Player" << turn(player) << ": please enter your move\n";
std::cin >> row, col;
answer = check(row, col);
}
if (player == 1)
Board[row][col] = 'X';
else if (player == 2)
Board[row][col] = 'O';
else
std::cout << "Failed.";
}
int TTTBoard::gameState(char x[][3]) //checks for a win or a draw
{
winner = 0;
int count = 0;
int a = row;
int b = col;
for (a = 0; a<3; a++)
{
for (b = 0; b<3; b++)
{
if (Board[a][b] == 0)
{
count++;
}
}
}
if (count > 0)
{
int row, col, xCheck, oCheck;
for (row = 0; row<3; row++)
{
xCheck = 0;
oCheck = 0;
for (col = 0; col<3; col++)
{
if (x[row][col] == 'X')
xCheck++;
if (x[row][col] == 'O')
oCheck++;
if (oCheck == 3)
{
winner = 2;
}
if (xCheck == 3)
{
winner = 1;
}
}
}
for (col = 0; col<3; col++)
{
xCheck = 0;
oCheck = 0;
for (row = 0; row<3; row++)
{
if (x[row][col] == 'X')
xCheck++;
if (x[row][col] == 'O')
oCheck++;
if (oCheck == 3)
{
winner = 2;
}
if (xCheck == 3)
{
winner = 1;
}
}
}
if (x[0][0] == 'X' && x[1][1] == 'X' && x[2][2] == 'X')
{
winner = 1;
}
else if (x[0][0] == 'O' && x[1][1] == 'O' && x[2][2] == 'O')
{
winner = 2;
}
else if (x[2][0] == 'X' && x[1][1] == 'X' && x[0][2] == 'X')
{
winner = 1;
}
else if (x[2][0] == 'O' && x[1][1] == 'O' && x[0][2] == 'O')
{
winner = 2;
}
}
else if (count == 9)
{
std::cout << "Its a draw.";
winner = 3;
}
else
{
std::cout << "It is the next players turn\n\n";
}
if (winner > 0)
{
done = true;
}
return done;
}
void TTTBoard::print(char Board[][3]) //prints current board state
{
std::cout << "\n";
std::cout << " 0 1 2\n";
std::cout << "0 " << Board[0][0] << " " << Board[0][1] << " " << Board[0][2] << " \n";
std::cout << "1 " << Board[1][0] << " " << Board[1][1] << " " << Board[1][2] << " \n";
std::cout << "2 " << Board[2][0] << " " << Board[2][1] << " " << Board[2][2] << " \n";
}
This one is also long.
TicTacToe.hpp
#ifndef TICTACTOE_HPP
#define TICTACTOE_HPP
#include "Board.hpp"
#include <iostream>
#include <string>
#include <iomanip>
class Board; //creates a board to be forward declared
class TicTacToe //creates tictactoe class
{
private:
int check(int, int);
int turn(int player);
int play(); //prototype for play method
int gameState(char x[][3]);
public:
int TtlGames, TtlP1, TtlP2, TtlDraws;
void intBoard();
Board* playBoard; //forward declarations for use in functions
Board* print;
Board* makeMove;
Board* BoardT;
};
#endif
TicTacToe.cpp
#include "Board.hpp"
#include "TicTacToe.hpp"
#include <iostream>
#include <string>
void TTTBoard::intBoard() //initializes board
{
done = false;
winner = 0;
player = 2;
player1 = 1;
player2 = 2;
draw = 3;
int i, k;
for (k = 0; k<3; k++)
{
for (i = 0; i<3; i++)
{
Board[k][i] = 0;
}
}
play();
}
int TicTacToe::turn(int player) //informs players of whose turn it is.
{
switch (player)
{
case 1: player = 2;
{
std::cout << "\nPlayers 1 turn.\n\n";
break;
}
case 2: player = 1;
{
std::cout << "\nPlayers 2 turn.\n\n";
break;
}
}
return player;
}
int TTTBoard::gameState(char x[][3]) //checks for win or draw
{
winner = 0;
int count = 0;
int a = row;
int b = col;
for (a = 0; a<3; a++)
{
for (b = 0; b<3; b++)
{
if (Board[a][b] == 0)
{
count++;
}
}
}
if (count > 0)
{
int row, col, xCheck, oCheck;
for (row = 0; row<3; row++)
{
xCheck = 0;
oCheck = 0;
for (col = 0; col<3; col++)
{
if (x[row][col] == 'X')
xCheck++;
if (x[row][col] == 'O')
oCheck++;
if (oCheck == 3)
{
winner = 2;
}
if (xCheck == 3)
{
winner = 1;
}
}
}
for (col = 0; col<3; col++)
{
xCheck = 0;
oCheck = 0;
for (row = 0; row<3; row++)
{
if (x[row][col] == 'X')
xCheck++;
if (x[row][col] == 'O')
oCheck++;
if (oCheck == 3)
{
winner = 2;
}
if (xCheck == 3)
{
winner = 1;
}
}
}
if (x[0][0] == 'X' && x[1][1] == 'X' && x[2][2] == 'X')
{
winner = 1;
}
else if (x[0][0] == 'O' && x[1][1] == 'O' && x[2][2] == 'O')
{
winner = 2;
}
else if (x[2][0] == 'X' && x[1][1] == 'X' && x[0][2] == 'X')
{
winner = 1;
}
else if (x[2][0] == 'O' && x[1][1] == 'O' && x[0][2] == 'O')
{
winner = 2;
}
}
else if (count == 9)
{
std::cout << "Its a draw.";
winner = 3;
}
else
{
std::cout << "It is the next players turn\n\n";
}
if (winner > 0)
{
done = true;
}
return done;
}
int TicTacToe::play() //initializes the game
{
int done = false;
Board* print(Board);
while (!done)
{
int count = 0;
Board* makeMove();
Board* (Board);
count++;
if (count != 9)
{
return !done;
}
else
{
done = true;
}
}
return 0;
}
int main() //main method
{
TicTacToe playGame;
playGame.TtlGames = 0, playGame.TtlP1 = 0,
playGame.TtlP2 = 0, playGame.TtlDraws = 0; //counters for total games, Player 1 Total,
int Winner = 0; //Player 2 Total , and Total draws.
char done = false;
while (!done)
{
// This will display before each game
std::cout << "Let's play a game of TicTacToe\n\n";
// Play a game and remember who won (if anyone)
playGame.intBoard();
}
// Finish
std::cout << "\n\nThank you for playing!\n";
std::cin.get();
std::cin.get();
return 0;
}
I attempted the suggestion by Code Fuller but it gave me this error.
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
So I thought maybe if I put the Main method in a separate file and link them all it might work. I got this:
/tmp/ccmSwwUz.o: In function `TTTBoard::intBoard()':
TicTacToe.cpp:(.text+0x0): multiple definition of `TTTBoard::intBoard()'
/tmp/ccSwOY9D.o:Board.cpp:(.text+0x0): first defined here
/tmp/ccmSwwUz.o: In function `TTTBoard::gameState(char (*) [3])':
TicTacToe.cpp:(.text+0x104): multiple definition of `TTTBoard::gameState(char (* ) [3])'
/tmp/ccSwOY9D.o:Board.cpp:(.text+0x288): first defined here
/tmp/ccSwOY9D.o: In function `TTTBoard::intBoard()':
Board.cpp:(.text+0xa7): undefined reference to `TTTBoard::play()'
/tmp/ccSwOY9D.o: In function `TTTBoard::makeMove()':
Board.cpp:(.text+0x176): undefined reference to `TTTBoard::turn(int)'
Board.cpp:(.text+0x19b): undefined reference to `TTTBoard::turn(int)'
/tmp/ccmSwwUz.o: In function `TTTBoard::intBoard()':
TicTacToe.cpp:(.text+0xa7): undefined reference to `TTTBoard::play()'
/tmp/ccz4019v.o: In function `main':
Main.cpp:(.text+0x48): undefined reference to `TicTacToe::intBoard()'
collect2: ld returned 1 exit status
So then I tried compiling the Board into an object first then linking TicTacToe and Main:
g++ Board.o TicTacToe.cpp Main.cpp -o TTT
and got the following errors:
/tmp/cc9h5kAs.o: In function `TTTBoard::intBoard()':
TicTacToe.cpp:(.text+0x0): multiple definition of `TTTBoard::intBoard()'
Board.o:Board.cpp:(.text+0x0): first defined here
/tmp/cc9h5kAs.o: In function `TTTBoard::gameState(char (*) [3])':
TicTacToe.cpp:(.text+0x104): multiple definition of `TTTBoard::gameState(char (*) [3])'
Board.o:Board.cpp:(.text+0x288): first defined here
Board.o: In function `TTTBoard::intBoard()':
Board.cpp:(.text+0xa7): undefined reference to `TTTBoard::play()'
Board.o: In function `TTTBoard::makeMove()':
Board.cpp:(.text+0x176): undefined reference to `TTTBoard::turn(int)'
Board.cpp:(.text+0x19b): undefined reference to `TTTBoard::turn(int)'
/tmp/cc9h5kAs.o: In function `TTTBoard::intBoard()':
TicTacToe.cpp:(.text+0xa7): undefined reference to `TTTBoard::play()'
/tmp/ccZlZ4Dn.o: In function `main':
Main.cpp:(.text+0x48): undefined reference to `TicTacToe::intBoard()'
collect2: ld returned 1 exit status
You trying to compile Board.cpp to executable file while it doesn't contain 'main' entrypoint. You have to compile Board.cpp to object file first:
gcc Board.cpp -c
Then you can compile TicTacToe.cpp and link it with Board.o:
gcc Board.o TicTacToe.cpp -o TicTacToe
I am trying to learn C++ and I have made litte tictactoe game but somethings wrong. I've tried to make the winner class both a void and a bool. But when I type in one coordinate it preforms the class. For making it simple you can only win if the 3 on top is O. Whats wrong?
SO if I input: 0 0 it says winner
Here's the code:
#include <iostream>
const int rows = 3;
const int elements = 3;
const char Ochar = 'O';
char board[rows][elements];
void Clear()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < elements; j++)
{
board[i][j] = 0;
}
}
}
void Show()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < elements; j++)
{
std::cout << " " << board[i][j] << " |";
}
std::cout << std::endl;
std::cout << "------------" << std::endl;
}
}
bool PlayerAttack(int x, int y)
{
if (board[x][y] == 0)
{
board[x][y] = Ochar;
return true;
}
return false;
}
void Winner()
{
if (board[0][0], board[0][1], board[0][2] = 'O')
{
std::cout << "Winner";
}
}
int main()
{
Clear();
Show();
int pos1 = 0;
int pos2 = 0;
while (1)
{
std::cout << "Please input a coordinate: "; std::cin >> pos1 >> pos2; std::cout << std::endl;
PlayerAttack(pos1, pos2);
Show();
Winner();
}
}
This line does not do what you think it does
if (board[0][0], board[0][1], board[0][2] = 'O')
You'd have to do
if (board[0][0] == 'O' && board[0][1] == 'O' && board[0][2] == 'O')
To use your Winner function to break your loop
bool Winner()
{
// You'll obviously have to check more than just this row
if (board[0][0] == 'O' && board[0][1] == 'O' && board[0][2] == 'O')
{
std::cout << "Winner";
return true;
}
return false;
}
Then in main
int main()
{
Clear();
Show();
int pos1 = 0;
int pos2 = 0;
bool winner = false;
while (!winner)
{
std::cout << "Please input a coordinate: "; std::cin >> pos1 >> pos2; std::cout << std::endl;
PlayerAttack(pos1, pos2);
Show();
winner = Winner(); // Use the returned bool
}
}
Good evening everyone, could anyone point me in the direction I need to go to get this code for a simple game of tic tac toe operational? I feel it is very close but I cannot get it to behave properly. Also, what could I use instead of break commands under the drawBoard command? Thanks in advance..
#include <iostream>
// This program allows user(s) to play a game of tic-tac-toe.
using namespace std;
// constants
const char SIGIL[3] = { '.', 'X', 'O' };
// prototypes
int winner(int board[3][3]);
void drawBoard(int board[3][3]);
bool isMoveLegal(int board[3][3]);
bool isGameOver(int board[3][3]);
// return 1 if player 1 'X' has won
// return 2 if player 2 'O' has won
// return 0 if neither player has won
int winner(int board[3][3]){
int win = 0;
// Checks for:
// X X X
for (int i = 0; i < 3; i++)
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
win = board[i][0];
// Checks for:
// X
// X
// X
for (int i = 0; i < 3; i++)
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
win = board[0][i];
// Checks for:
// X X
// X or X
// X X
if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) ||
(board[0][2] == board[1][1] && board[1][1] == board[2][0]))
win = board[1][1];
return win;
}
// using this board as a guide
// draw the board using "." for empty squares
// or 'X' or 'O' for player 1 or player 2
void drawBoard(int board[3][3]){
cout << " 0 1 2" << endl;
for (int i = 0; i < 3; i++){
cout << i ;
for (int j = 0; j < 3; j++){
cout.width(3);
switch (board[i][j])
{
case 0:{
cout << ".";
}break; case 1:{
cout << "X";
}break;
case 2:{
cout << "0";
}break;
default:
break;
}
} cout << endl;
}
}
// return false if row or column are out of bounds
// or if that spot on the board is already taken
// otherwise return true
bool isMoveLegal(int board[3][3], int row, int column){
if (row >= 0 && row <= 3 && column <= 3 && column >= 0) {
if (board[row][column] == 0)
return true;
else return false;
}
return false;
}
// if any player has three in a row or if the board is full
// return true otherwise return false
bool isGameOver(int board[3][3]){
if (winner(board) == 1 || winner(board) == 2) return true;
for (int r = 0; r <= 2; r++)
for (int c = 0; c <= 2; c++)
if (board[r][c] == 0)
return false;
return true;
}
int main(){
int board[3][3] = { { 0 } }; // 0 for empty square, 1 or 2 for taken squares
int player = 1;
int row, column, result;
bool legalMove;
// starting board
drawBoard(board);
while (!isGameOver(board)){
cout << "Player " << player << "(" << SIGIL[player] << "), your move?";
cin >> row >> column;
legalMove = isMoveLegal(board, row, column);
while (!legalMove){
cout << "Player " << player << "(" << SIGIL[player] << "), your move?";
cin >> row >> column;
legalMove = isMoveLegal(board, row, column);
}
board[row][column] = player;
drawBoard(board);
player = 3 - player;
}
// game over
result = winner(board);
if (result == 0){
cout << "Tie Game" << endl;
}
else {
cout << "Player " << result << "(" << SIGIL[result] << ") wins!" << endl;
}
return 0;
}
This piece of code will go out of bounds:
bool isMoveLegal(int board[3][3], int row, int column){
if (row >= 0 && row <= 3 && column <= 3 && column >= 0) {
if (board[row][column] == 0)
return true;
else return false;
}
Remember that arrays are 0-indexed, so it should be:
bool isMoveLegal(int board[3][3], int row, int column){
if (row >= 0 && row < 3 && column < 3 && column >= 0) {
if (board[row][column] == 0)
return true;
else return false;
}
Your break statements in drawBoard are for the switch statement, not a loop. They are okay, however, you should use board[i][j] as an index into SIGIL:
// constants
const char SIGIL[3] = { '.', 'X', 'O' };
// ...
void drawBoard(int board[3][3])
{
cout << " 0 1 2\n";
for (int i = 0; i < 3; ++i)
{
cout << i ;
for (int j = 0; j < 3; ++j)
{
cout << SIGIL[board[i][j]] << " ";
}
cout << endl;;
}
}
I've implemented Negamax as it can be found on wikipedia, which includes alpha/beta pruning.
However, it seems to favor a losing move, which is an invalid result to my knowledge.
The game is Tic-Tac-Toe, I've abstracted most of the game play so it should be rather easy to spot an error within the algorithm.
#include <list>
#include <climits>
#include <iostream>
//#define DEBUG 1
using namespace std;
struct Move {
int row, col;
Move(int row, int col) : row(row), col(col) { }
Move(const Move& m) { row = m.row; col = m.col; }
};
struct Board {
char player;
char opponent;
char board[3][3];
Board() { }
void read(istream& stream) {
stream >> player;
opponent = player == 'X' ? 'O' : 'X';
for(int row = 0; row < 3; row++) {
for(int col = 0; col < 3; col++) {
char playa;
stream >> playa;
board[row][col] = playa == '_' ? 0 : playa == player ? 1 : -1;
}
}
}
void print(ostream& stream) {
for(int row = 0; row < 3; row++) {
for(int col = 0; col < 3; col++) {
switch(board[row][col]) {
case -1:
stream << opponent;
break;
case 0:
stream << '_';
break;
case 1:
stream << player;
break;
}
}
stream << endl;
}
}
void do_move(const Move& move, int player) {
board[move.row][move.col] = player;
}
void undo_move(const Move& move) {
board[move.row][move.col] = 0;
}
bool isWon() {
if (board[0][0] != 0) {
if (board[0][0] == board[0][1] &&
board[0][1] == board[0][2])
return true;
if (board[0][0] == board[1][0] &&
board[1][0] == board[2][0])
return true;
}
if (board[2][2] != 0) {
if (board[2][0] == board[2][1] &&
board[2][1] == board[2][2])
return true;
if (board[0][2] == board[1][2] &&
board[1][2] == board[2][2])
return true;
}
if (board[1][1] != 0) {
if (board[0][1] == board[1][1] &&
board[1][1] == board[2][1])
return true;
if (board[1][0] == board[1][1] &&
board[1][1] == board[1][2])
return true;
if (board[0][0] == board[1][1] &&
board[1][1] == board[2][2])
return true;
if (board[0][2] == board [1][1] &&
board[1][1] == board[2][0])
return true;
}
return false;
}
list<Move> getMoves() {
list<Move> moveList;
for(int row = 0; row < 3; row++)
for(int col = 0; col < 3; col++)
if (board[row][col] == 0)
moveList.push_back(Move(row, col));
return moveList;
}
};
ostream& operator<< (ostream& stream, Board& board) {
board.print(stream);
return stream;
}
istream& operator>> (istream& stream, Board& board) {
board.read(stream);
return stream;
}
int evaluate(Board& board) {
int score = board.isWon() ? 100 : 0;
for(int row = 0; row < 3; row++)
for(int col = 0; col < 3; col++)
if (board.board[row][col] == 0)
score += 1;
return score;
}
int negamax(Board& board, int depth, int player, int alpha, int beta) {
if (board.isWon() || depth <= 0) {
#if DEBUG > 1
cout << "Found winner board at depth " << depth << endl;
cout << board << endl;
#endif
return player * evaluate(board);
}
list<Move> allMoves = board.getMoves();
if (allMoves.size() == 0)
return player * evaluate(board);
for(list<Move>::iterator it = allMoves.begin(); it != allMoves.end(); it++) {
board.do_move(*it, -player);
int val = -negamax(board, depth - 1, -player, -beta, -alpha);
board.undo_move(*it);
if (val >= beta)
return val;
if (val > alpha)
alpha = val;
}
return alpha;
}
void nextMove(Board& board) {
list<Move> allMoves = board.getMoves();
Move* bestMove = NULL;
int bestScore = INT_MIN;
for(list<Move>::iterator it = allMoves.begin(); it != allMoves.end(); it++) {
board.do_move(*it, 1);
int score = -negamax(board, 100, 1, INT_MIN + 1, INT_MAX);
board.undo_move(*it);
#if DEBUG
cout << it->row << ' ' << it->col << " = " << score << endl;
#endif
if (score > bestScore) {
bestMove = &*it;
bestScore = score;
}
}
if (!bestMove)
return;
cout << bestMove->row << ' ' << bestMove->col << endl;
#if DEBUG
board.do_move(*bestMove, 1);
cout << board;
#endif
}
int main() {
Board board;
cin >> board;
#if DEBUG
cout << "Starting board:" << endl;
cout << board;
#endif
nextMove(board);
return 0;
}
Giving this input:
O
X__
___
___
The algorithm chooses to place a piece at 0, 1, causing a guaranteed loss, do to this trap(nothing can be done to win or end in a draw):
XO_
X__
___
I'm pretty sure the game implementation is correct, but the algorithm should be aswell.
EDIT: Updated evaluate and nextMove.
EDIT2: Fixed first problem, there still seem to be bugs though
Your evaluate function counts the empty spaces, and does not recognize a winning board.
EDIT:
There's also a relatively minor problem in nextMove. The line should be
int score = -negamax(board, 0, -1, INT_MIN + 1, INT_MAX);
Fix that (and evaluate), and the code chooses the right move.
EDIT:
This fixes it:
if (board.isWon() || depth <= 0) {
#if DEBUG > 1
cout << "Found winner board at depth " << depth << endl;
cout << board << endl;
#endif
return -100;
}
Almost all of these problems stem from not being clear about the meaning of score. It is from the point of view of player. If negamax is evaluating the position of player 1, and player 1 cannot win, the score should be low (e.g. -100); if negamax is evaluating the position of player -1, and player -1 cannot win, the score should be low (e.g. -100). If evaluate() can't distinguish the players, then returning a score of player * evaluate(board) is just wrong.
isWon returns true for both a win or a loss of the player. That can't be helping.
There seems to be something funny with the use of player.
Your toplevel loop calls "board.do_move(*it, 1);" then calls negamax with player=1.
Then negamax will call "board.do_move(*it, player);", so it looks like the first player is effectively getting 2 moves.