Choose X or O for move tic tac toe - c++

I am making a Tic Tac Toe game and i created a function that inserts X or O into my array. I have run into one problem with my design. I call the function to make a move for X, but when it is the next players turn how do i make it call for O?
Is there a way after i put makeMove() i can just call somehow it to take in O turn instead of X. Because as you can see if i do X it will just always ask for X and not O. How can i make it choose to pull in X or O turn.
The problem is i need to only have one function that makes moves.
int main()
{
while(SOME CONDITION HERE)
{
printBoard();
cout << "Player X please choose a position: ";
makeMove('X');
cout << "Player O please choose a position: ";
makeMove('O');
}
}
int makeMove(char marker)
{
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = marker;
}

Start with this:
int main()
{
while(SOME CONDITION HERE)
{
printBoard();
cout << "Player X please choose a position: ";
makeMove('X');
cout << "Player O please choose a position: ";
makeMove('O');
}
}
int makeMove(char marker)
{
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = marker;
}
Note that you're going to want to change the SOME CONDITION HERE part, but you could quickly replace it by 1 and get the same behavior of your current script (actually, a bit better).
But you'll eventually want to put something there that makes sense -- something that will tell the program to stop prompting the players for positions and, say, declare a winner.
The following is just a more streamlined way of doing the same thing:
int main()
{
while(SOME CONDITION HERE)
{
printBoard();
makeMove('X');
makeMove('O');
}
}
int makeMove(char marker)
{
cout << "Player " << marker << " please choose a position: ";
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = marker;
return 0;
}
Note the added return 0 -- if you don't want to return something, you should just make makeMove return void so as not to be confusing.

You might try using an argument:
int makeMove(char player);
makeMove('O');
makeMove('X');

First of all, don't call main() recursively. Use a loop instead.
Secondly, use a variable (such as player below) to indicate whose turn it is.
int main()
{
char player = 'X';
while (/* game not finished */) {
printBoard();
makeMove(player);
player = (player == 'X') ? 'O' : 'X';
}
}
void makeMove(char player)
{
cout << "Player " << player << " please choose a position: ";
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = player;
}

Something like this may work... just be sure to use a loop for the moves.
char player = 'X';
while(...) {
cout << "choose position...";
makeMove(player);
if(player == 'X')
player = 'O';
else
player = 'X';
...
}
//in make move:
int makeMove(char player) {
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = player;
}

http://scripts.franciscocharrua.com/javascript/tic-tac-toe/
I added this to my website a few months ago. I admit it may be a bit complex, and in JavaScript, but it may be of some help.
JS:
function tic_tac_toe(blank_token, player_tokens, artificial_intelligence)
{
this.board = [[blank_token, blank_token, blank_token],
[blank_token, blank_token, blank_token],
[blank_token, blank_token, blank_token]];
this.blank_token = blank_token;
this.player_tokens = player_tokens;
this.display_choice = function() {};
this.declare_human_win = function() {};
this.declare_computer_win = function() {};
this.declare_tie = function() {};
this.artificial_intelligence = artificial_intelligence;
this.start =
function()
{
//Randomly choose a token for the human player.
var human_token_index = Math.floor(Math.random() * this.player_tokens.length);
this.human_player = this.player_tokens[human_token_index];
//Place the chosen token at the end of the array.
this.player_tokens[human_token_index] = this.player_tokens[this.player_tokens.length - 1];
this.player_tokens[this.player_tokens.length - 1] = this.human_player;
//Randomly choose a different token for the computer player.
var computer_token_index = Math.floor(Math.random() * (this.player_tokens.length - 1));
this.computer_player = this.player_tokens[computer_token_index];
//Clear the board.
for(var row = 0; row < 3; row++)
for(var collumn = 0; collumn < 3; collumn++)
{
this.place(this.blank_token, row, collumn);
}
if(Math.random() < 0.5)
{
this.turn = this.computer_player;
this.computer_turn();
}
else
{
this.turn = this.human_player;
}
};
//Returns the token of the winning player.
//If no one has won yet or the game is tied, returns the blank token.
//Used in combination with blank_token_count() to determine if the game is tied.
this.winner =
function()
{
var winner = this.blank_token;
//Check for 3 consecutive horisontal tokens.
for(var row = 0; row < 3; row++)
{
winner = this.board[row][0];
for(var collumn = 1; collumn < 3; collumn++)
{
if(this.board[row][collumn] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
}
//Check for 3 consecutive vertical tokens.
for(var collumn = 0; collumn < 3; collumn++)
{
winner = this.board[0][collumn];
for(var row = 1; row < 3; row++)
{
if(this.board[row][collumn] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
}
//Check for 3 consecutive diagonal tokens.
winner = this.board[0][0];
for(var row = 1; row < 3; row++)
{
if(this.board[row][row] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
winner = this.board[0][2];
for(var row = 1; row < 3; row++)
{
if(this.board[row][2 - row] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
return(winner);
};
this.blank_token_count =
function()
{
var blank_token_count = 0;
for(var row = 0; row < 3; row++)
for(var collumn = 0; collumn < 3; collumn++)
{
if(this.board[row][collumn] == this.blank_token)
{
blank_token_count++;
}
}
return(blank_token_count);
};
this.computer_turn =
function()
{
//Lets the computer take its turn if the game is not over.
if(this.turn != this.blank_token)
{
this.turn = this.computer_player;
var computer_move = this.artificial_intelligence();
this.place(this.computer_player, computer_move.row, computer_move.collumn);
}
};
this.human_turn =
function(row, collumn)
{
this.place(this.human_player, row, collumn);
this.computer_turn();
}
this.place =
function(token, row, collumn)
{
if(row < 3 && collumn < 3 &&
((this.turn == token && this.board[row][collumn] == this.blank_token) || token == this.blank_token))
{
this.board[row][collumn] = token;
this.display_choice(token, row, collumn)
//Finishes the game in case a of a win or a tie.
//When the board is not being reset.
if(token != this.blank_token)
{
var winner_token = this.winner();
if(winner_token == this.human_player)
{
this.declare_human_win();
this.turn = this.blank_token;
}
if(winner_token == this.computer_player)
{
this.declare_computer_win();
this.turn = this.blank_token;
}
if(winner_token == this.blank_token && this.blank_token_count() == 0)
{
this.declare_tie();
this.turn = this.blank_token;
}
//Gives the human player a turn, if the game is not over.
if(this.turn == this.computer_player)
{
this.turn = this.human_player
}
}
}
};
}

Related

Implementing Minimax Algorithm with two tasks

I have a major problem in my minimax algorithm. I have to implement a game, where is a player and an AI player. Both of them can step up,down,right,left diagonal and after that they have to block a cell, where the other player can't step (ofc, where the other player stays is a blocked cell and can't block that one, and you can't block an already blocked cell too). I wrote a little minimax algorithm for that, but for a strange thing the AI can't decide the best root.
struct Position
{
int x, y;
} MaxP, MinP;
int k = 2;
char board[10][10];
int currentPlayer = 2;
//Here are my global variables, MaxP is the AI, and MinP is the player.
I set the cells B (as blocked) around my table.
The minimax calculation algorithm:
int nyertesErtek(int result) //return a winning value, if result=1 Ai Wins, if result=2 Player Wins, if result=0, then the game it's still going
{
if (result == 1) return 10;
if (result == 2) return -10;
}
int minimax(char pBoard[10][10], int depth, bool isMaximizing)
{
int result = 0;
if (isMaximizing==true)
{
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
bool lephetMax = false;
bool lephetMin = false;
for (int i = 0; i < 8; i++)
{
if (pBoard[MaxP.x + checkX[i]][MaxP.y + checkY[i]] != 'B')
{
lephetMax = true;
break;
}
}
if (lephetMax == false)
{
result = 2;
}
}
if (isMaximizing == false)
{
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
bool lephetMin = false;
for (int i = 0; i < 8; i++)
{
if (pBoard[MinP.x + checkX[i]][MinP.y + checkY[i]] != 'B')
{
lephetMin = true;
break;
}
}
if (lephetMin == false)
{
result = 1;
}
}
if (result != 0) //ha nem terminal state
{
//cout << "Resultra jutott"<<endl;
//cout << "---------------->Kovetkezne a: " << isMaximizing << " Result=" << result << " NyeresErtek=" << nyertesErtek(result) <<" depth="<<depth<< "<---------------"<<endl;
//printBoard();
return nyertesErtek(result);
}
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
if (isMaximizing)
{
int bestScore = -INT_MAX;
int szabadX;
int szabadY;
for (int l = 0; l < 8; l++)
{
if (pBoard[MaxP.x + checkX[l]][MaxP.y + checkY[l]] != 'B')
{
int oldMaxPX = MaxP.x;
int oldMaxPY = MaxP.y;
MaxP.x = MaxP.x + checkX[l];
MaxP.y= MaxP.y + checkY[l];
pBoard[MaxP.x][MaxP.y] = 'B';
pBoard[oldMaxPX][oldMaxPY] = 'o';
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= k; j++)
{
if (pBoard[i][j] != 'B')
{
szabadX = i;
szabadY = j;
pBoard[szabadX][szabadY] = 'B';
//cout << "Maximizing, depth=" << depth << endl;
//printBoard();
int score = minimax(pBoard, depth + 1, false);
pBoard[szabadX][szabadY] = 'o';
if (score > bestScore)
{
bestScore = score;
}
}
}
}
pBoard[MaxP.x][MaxP.y] = 'o';
pBoard[oldMaxPX][oldMaxPY] = 'B';
MaxP.x = oldMaxPX;
MaxP.y = oldMaxPY;
}
}
return bestScore;
}
else
{
int bestScore = INT_MAX;
int szabadX;
int szabadY;
for (int l = 0; l < 8; l++)
{
if (pBoard[MinP.x + checkX[l]][MinP.y + checkY[l]] != 'B')
{
int oldMinPX = MinP.x;
int oldMinPY = MinP.y;
MinP.x = MinP.x + checkX[l];
MinP.y = MinP.y + checkY[l];
//pBoard[MinP.x + checkX[l]][MinP.y + checkY[l]] = 'B';
pBoard[MinP.x][MinP.y] = 'B';
pBoard[oldMinPX][oldMinPY] = 'o';
//cout << "Minimizing depth= " << depth << endl;
//printBoard();
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= k; j++)
{
if (pBoard[i][j] != 'B')
{
szabadX = i;
szabadY = j;
pBoard[szabadX][szabadY] = 'B';
int score = minimax(pBoard, depth + 1, true);
//pBoard[MinP.x + checkX[l]][MinP.y + checkY[l]] = 'o';
pBoard[szabadX][szabadY] = 'o';
if (score < bestScore)
{
bestScore = score;
}
}
}
}
pBoard[MinP.x][MinP.y] = 'o';
pBoard[oldMinPX][oldMinPY] = 'B';
MinP.x = oldMinPX;
MinP.y = oldMinPY;
}
}
return bestScore;
}
}
And moving the AI is in this function:
void bestMove() {
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
int bestScore = -INT_MAX;
Position move;
int AIBlockX, AIBlockY;
int szabadX;
int szabadY;
for (int l = 0; l < 8; l++)
{
if (board[MaxP.x + checkX[l]][MaxP.y + checkY[l]] != 'B')
{
int oldMaxPX = MaxP.x;
int oldMaxPY = MaxP.y;
MaxP.x = MaxP.x + checkX[l];
MaxP.y = MaxP.y + checkY[l];
board[MaxP.x][MaxP.y] = 'B';
board[oldMaxPX][oldMaxPY] = 'o';
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= k; j++)
{
if (board[i][j] != 'B')
{
szabadX = i;
szabadY = j;
board[szabadX][szabadY] = 'B';
int score = minimax(board, 0, false);
cout << endl << "Ennyi a score amit kaptam pech=" << score << endl;
board[szabadX][szabadY] = 'o';
if (score > bestScore)
{
bestScore = score;
move.x = MaxP.x;
move.y = MaxP.y;
AIBlockX = szabadX;
AIBlockY = szabadY;
cout << "BESTMOVE: " << move.x << " " << move.y << " bestscore= " << bestScore << endl;
}
}
}
}
board[MaxP.x][MaxP.y] = 'o';
board[oldMaxPX][oldMaxPY] = 'B';
MaxP.x = oldMaxPX;
MaxP.y = oldMaxPY;
}
}
board[move.x][move.y] = 'B';
board[MaxP.x][MaxP.y] = 'o';
MaxP.x = move.x;
MaxP.y = move.y;
board[AIBlockX][AIBlockY] = 'B';
currentPlayer = 2;
}
I think my main problem is something in the minimax function: when I check where the player can go -> and after that all the possible blocking moves. And in that triple for when I rewrite the best score with the current score I can't return the value directly because I have to check other possible moves in the firs for iteration.
So after all (:D) my question is that how can I save the best move after the cell blocking was done and return that to my AI to step there? Thank you for you answer. :)
ps:I'm sorry if this post is too long, but I thought to fully understand my problem, you also have to see the algorithm part.

C++ tic tac toe game only wins with one combination

I want the program to print "You win" when any of the instances in the champion() function are given. It only shows a winner when "123" is inputted. Whenever three X's are displayed anywhere else the program continues. For instance if three X's are given diagonally the program will still continue. Novice programmer so any criticism is greatly appreciated.
class TicTacToe {
private:
char map[GRID_SIZE][GRID_SIZE];
public:
void computers_turn() {
while (true) {
int choice = (rand() % 9) + 1;
int row = choice / 3;
int col = choice % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'O';
break;
}
}
}
void champion() {
const char* possiblities[8] = {"123", "456", "789", "147",
"258", "369", "159", "753"};
for (int i = 0; i < 8; i++) {
char previous_pos = '0';
bool winner = true;
const char* possible_moves = possiblities[i];
for (int index = 0; index < GRID_SIZE; index++) {
char character = possible_moves[i];
int entered_num = character - '0';
int grid_space = entered_num - '1';
int row = index / GRID_SIZE;
int col = index % GRID_SIZE;
char grid_coordinate = map[row][col];
if (previous_pos == '0') {
previous_pos = grid_coordinate;
} else if (previous_pos == grid_coordinate) {
continue;
} else {
winner = false;
break;
}
}
if (winner) {
puts("You win");
exit(0);
break;
}
}
}
void playgame() {
std::string input;
while (true) {
std::cout << "Go player one" << std::endl;
getline(std::cin, input);
if (input != " ") {
char entered = input.c_str()[0];
if (entered >= '1' && entered <= '9') {
int entered_num = entered - '0';
int index = entered_num - 1;
int row = index / 3;
int col = index % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'X';
break;
}
} else {
std::cout << "Only numbers 1 - 9" << std::endl;
}
} else {
std::cout << "Have to enter something, try again" << std::endl;
}
}
}
void generateGrid() {
int number = 1;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
map[x][y] = std::to_string(number).c_str()[0];
number += 1;
}
}
}
void tictacToeMap() {
std::cout << std::endl;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
std::printf(" %c ", map[x][y]);
}
std::cout << std::endl;
}
}
TicTacToe() {
generateGrid();
while (true) {
champion();
tictacToeMap();
playgame();
computers_turn();
}
}
};
int main() {
TicTacToe ticTacToe;
return 0;
}

C++ 2d array duplication error in game

I'm new to C++ and I'm trying to figure out why I get two "*" symbols in my game board when I'm moving around. The game is supposed to be about avoiding the troll (#). But I am getting duplicate # and * symbols, and I can't figure out why. It seems that the problem is either in one of the for loops or in the posX or posY variables, which I found out by commenting out segments of the code:
#include <iostream>
#include <string>
using namespace std;
void ClearScreen()
{
cout << string(100, '\n');
}
main()
{
int size_arrx = 10;
int size_arry = 20;
int posX = 0;
int posY = 0;
int trollX = size_arrx - 1;
int trollY = size_arry - 1;
char a[size_arry][size_arrx];
bool Alive = true;
char player = '*';
char troll = '#';
while (Alive == true) {
ClearScreen();
for (int i = 0; i<size_arrx; i++)
{
for (int j = 0; j<size_arry; j++)
{
a[i][j] = 'x';
}
}
for (int i = 0; i<size_arrx; i++)
{
for (int j = 0; j<size_arry; j++)
{
a[posX][posY] = player;
a[trollX][trollY] = troll;
cout << a[i][j];
if (posX< 0) {
a[posX = 0][posY] = player;
cout << a[i][j];
}
else if (posY< 0) {
a[posX][posY = 0] = player;
cout << a[i][j];
}
else if (posY > size_arry - 1) {
a[posX][posY = size_arry - 1] = player;
cout << a[i][j];
}
else if (posX > size_arrx - 1) {
a[posX = size_arrx - 1][posY] = player;
cout << a[i][j];
}
}
cout << endl;
}
char dir;
cin >> dir;
if (dir == 'w') {
trollX++;
posX--;
}
if (dir == 's') {
trollX--;
posX++;
}
if (dir == 'd') {
trollY--;
posY++;
}
if (dir == 'a') {
trollY++;
posY--;
}
}
if ((trollX == posX) && (trollY == posY)) {
Alive == false;
}
}
The result looks like this. I only want one *. The * can move perfectly fine, but a duplicate * follows the original * but 11 X's away.
xxxxxxxxxx*xxxxxxxxx <---- This is a duplicate *
*xxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxx#
xxxxxxxxx#xxxxxxxxxx <---- This is a duplicate #
Thanks in advance if you can help me
for (int i=0;i<size_arrx;i++){
for (int j=0;j<size_arry;j++){
a[i][j]='x';
}
}
a[posX][posY]=player;
a[trollX][trollY]=troll;
for (int i=0;i<size_arrx;i++){
for (int j=0;j<size_arry;j++){
cout << a[i][j];
Using this code gave the same error. I'm interpreting this as a[i][j]='x' populates all positions of a[][] with X's. a[posX][posY]=player; overwrites the position of the player with an * (could be x 2 y 5 for example) and then the board gets printed by cout << a[i][j];. I don't understand how a duplicate symbol gets thrown in there.
Let's simplify your program.
Initialize the board outside of the while loop.
There should be no reason to keep initializing it:
for (unsigned int row = 0; row < size_arry; ++row)
{
std::fill(&a[row][0], &a[row][size_arrx], 'x'); // Fill a row.
}
Printing the board should be simple:
for (unsigned int row = 0; row < size_arry; ++row)
{
for (unsigned int column = 0; column < size_arrx; ++column)
{
cout << a[row][column];
}
cout << '\n';
}
Now the character logic.
Every character has a position, row and column, of where it is. To ease restoration, every character should have a previous position also.
struct Position
{
unsigned int row;
unsigned int column;
};
Sorry about that code, the fingers and keyboard are not cooperating.
To move a character to a valid new position, you have to restore the previous position:
unsigned int player_now_x;
unsigned int player_now_y;
unsigned int player_prev_x;
unsigned int player_prev_y;
//...
a[player_prev_y][player_prev_x] = 'x';
a[player_now_y][player_now_y] = player;
For processing single letter commands, a switch statement may be more readable:
// Update previous position.
player_prev_x = player_now_x;
player_prev_y = player_now_y;
switch (dir)
{
case 'd':
if (player_now_y < size_arry)
{
++player_now_y;
}
break;
case 's':
if (player_now_x < size_arrx)
{
++player_now_x;
}
break;
// ...
}
Simplifications.
You can print the board with one cout if you add an extra column. The ending column of each row (except the last) will have a line ending character, '\n'. The last column of the last row will have a termination character, '\0'.
struct Board
{
void set_player(const Position& pos, char player_token)
{
a[pos.x][pos.y] = player_token;
}
void move_player(const Position& new_position,
const Position& previous_position,
char player_token)
{
set_player(previous_position, 'x');
set_player(new_position, player_token);
}
void print()
{
std::cout << &a[0][0] << "\n";
}
Board()
{
for (unsigned int y = 0; y < size_arry; ++y)
{
std::fill(&a[y][0], &a[y][size_arrx], 'x');
a[y][size_arrx - 1] = '\n';
}
a[size_arry - 1][size_arrx - 1] = '\0';
}
};
//...
Board b;
Position player_now;
Position player_prev;
const char player_token = '*';
//...
switch (dir)
{
case 'd':
if (player_now.y < size_arry)
{
++player_now.y;
}
//...
}
b.move_player(player_now, player_previous, player_token);
Sorry again, for the above code fragment, it's the fingers typing out what they want.

Derived Classes not printing properly

Im making this console game and the way im doing it is printing chars to the console from a 3 dimentional array called map. Which is assigned using the chars of the monsters, characters and background. The problem is i have been able to assign to the map array and print of successfully the char taken a monster class. But for some reason the derived character class objects aren't having their chars printed.
I am confident this is not an access issue cause there are no compiling errors and when the program runs there are empty gaps on the row(not the exact index but the right row index) that the characters are assigned to.
Here is the code that assigns it:
void game::assignScreen() {
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 40; col++) {
if (col == 0 || col == 39) {
map[row][col] = (char) 124;
} else if (row == 0 || row == 19) {
map[row][col] = (char) 95;
} else {
map[row][col] = (char) 46;
}
}
}
switch (difficulty) {
case 1:
for (int i=0; i <2; i++){
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
case 2:
if (difficulty == 2) {
for (int i = 0; i <4; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
}
map[elfPlayer.getPos(true)][elfPlayer.getPos(false)] = elfPlayer.getSymbol();
map[guardPlayer.getPos(true)][guardPlayer.getPos(false)] = guardPlayer.getSymbol();
map[knightPlayer.getPos(true)][knightPlayer.getPos(false)] = knightPlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
break;
case 3:
for (int i = 0; i <6; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
case 4:
if (difficulty == 4) {
for (int i = 0; i <9; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
}
map[elfPlayer.getPos(true)][elfPlayer.getPos(false)] = elfPlayer.getSymbol();
map[guardPlayer.getPos(true)][guardPlayer.getPos(false)] = guardPlayer.getSymbol();
map[knightPlayer.getPos(true)][knightPlayer.getPos(false)] = knightPlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
break;
}
}
And this prints it
void game::printScreen(string msg) {
clearScreen();
cout << msg;
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 40; col++) {
if (map[row][col] == 'E' || map[row][col] == 'G' || map[row][col] == 'K' ||
map[row][col] == 'R' || map[row][col] == 'W') {
if (getPlayer(map[row][col]).getStatus() == 1) {
changeColor(14, false);
cout << map[row][col];
changeColor(15, false);
} else if (getPlayer(map[row][col]).getStatus() == 2 || getPlayer(map[row][col]).getStatus() == 3) {
changeColor(4, false);
cout << map[row][col];
changeColor(15, false);
}
} else {
cout << map[row][col];
}
}
cout << endl;
}
}
getPlayer is a function that takes the currently saved/selected char and returns the object it belongs to
position
int character::getPos(bool getX) {
if (getX) {
return xPos;
} else {
return yPos;
}
}
returns char
char character::getSymbol() {
return symbol;
}
header file
class character
{
public:
character();
~character();
string getName();
char getSymbol();
int getStatus();
int getPos(bool);
void setPos(int, int);
void setStatus(bool, bool);
protected:
string className;
char symbol;
private:
int xPos;
int yPos;
};
from game header file
monster *enemy[21];
elf elfPlayer;
guard guardPlayer;
knight knightPlayer;
rogue roguePlayer;
wizard wizardPlayer;
printScreen(elfPlayer.getName());
cout << elfPlayer.getSymbol();
I tested whether the postions for the objects can be printed, it's working for *enemy[], the derived classes look fine. I really have no idea why it's not printing right. Maybe im making a stupid mistake id just like some insight.
What happens when the map is printed, the bottom right empty area is meant to be full of chars
I turns out it was just a very silly mistake on my part. Thanks to Simon Kraemer for finding the problem.
I just added another else to print out stuff to the character if statement inside of the printScreen method.
Btw, what does it matter if i have a get positon function like that, it uses less space and is quicker to use. Also this is not a group project so confusion is not an issue (if i was in a group perhaps id change it).

Game of Life array edges acting weird

I saw Conway's Game of Life and decided to make my own.
I have a bool array to represent the world, but the edges (Top and bottom) are acting weird, random cells becomes live.
In this code, it does not print the bottom and top of the world, but this is a bad solution.
The world "wraps" at the right and the left, causing even more problems, but that is for another time.
#include <iostream>
const int height = 20;
const int width = 20;
bool now_world[height][width];
bool then_world[height][width];
void clear_world();
void place_random_live_cells();
void then_world_initialization();
void print_world();
void generation_pass();
void update_worlds();
int main(int argc, const char * argv[])
{
using namespace std;
srand((unsigned)time(NULL));
int timer = 0;
int generation = 0;
clear_world();
place_random_live_cells();
then_world_initialization();
bool running = true;
while (running) {
if (timer == 50000000) {
cout << "Generation #" << generation << endl;
print_world();
generation_pass();
update_worlds();
++generation;
timer = 0;
}
++timer;
}//While (running) ends here
return 0;
}
void place_random_live_cells()
{
int percent = 30;
int max_live_cells = ((height * width) / 100) * percent;
int current_live_cells = 0;
while (current_live_cells < max_live_cells) {
int ycoords = 0 + (rand() % (height + 1));
int xcoords = 0 + (rand() % (width + 1));
if (now_world[ycoords][xcoords] == false) {
now_world[ycoords][xcoords] = true;
} else {
current_live_cells--;
}
++current_live_cells;
}
}
//A generation pass and cells die and some cells come to life
void generation_pass()
{
using namespace std;
int neighbours = 0;
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii+1][jjj ] == true) {
++neighbours;
}
if (now_world[iii+1][jjj-1] == true) {
++neighbours;
}
if (now_world[iii ][jjj+1] == true) {
++neighbours;
}
if (now_world[iii ][jjj-1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj ] == true) {
++neighbours;
}
if (now_world[iii-1][jjj-1] == true) {
++neighbours;
}
//Apply rules to the cells
//Dead cells with three live neighbours becomes alive
if (then_world[iii][jjj] == false && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with fewer than two, they die
if (then_world[iii][jjj] == true && neighbours < 2) {
then_world[iii][jjj] = false;
}
//Alive with 2 or three live neighbours live on unchanged
if (then_world[iii][jjj] == true && neighbours == 2) {
then_world[iii][jjj] = true;
}
if (then_world[iii][jjj] == true && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with more than three, they die
if (then_world[iii][jjj] == true && neighbours > 3) {
then_world[iii][jjj] = false;
}
//Dead cells without exactly three live neighbours remain dead
//Reset neighbour value to zero
neighbours = false;
}
}
}
//Make next generation identical to current
//This is only called once
void then_world_initialization()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
then_world[iii][jjj] = now_world[iii][jjj];
}
}
}
//Make the next generation be today
//This is called every generation
void update_worlds()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = then_world[iii][jjj];
}
}
}
//Set all cells to dead
void clear_world()
{
for (long iii = 0; iii < height; iii++) {
for (long jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = false;
then_world[iii][jjj] = false;
}
}
}
//Print world
void print_world()
{
using namespace std;
char live = 'X';
char dead = '.';
for (long iii = height; iii > 0; iii--) {
for (long jjj = width; jjj > 0; jjj--) {
if (iii != 0 && iii != height) {
if (now_world[iii][jjj]) {
cout << live;
} else {
cout << dead;
}
cout << " ";
}
}
cout << endl;
}
cout << endl;
}
Having done this for a course I taught in the past, the most common issue I always see people having is going outside the bounds of the array they're using.
If you look at the if statements in your nested for loop, I think you'll find some issues. For instance, in this case, what happens when iii equals (height-1) or jjj equals (width-1)?
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
You're going outside the bounds of your array and so your results will be undefined. You may get segfaults, but you may just also get spurious data. C++ doesn't enforce you staying within the bounds of the array you define.
Make sure you also handle cases like this:
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
What if iii equals zero?
Hope that helps.
You're trying to access out-of-boundary indexes in your array.
I'm not sure what behaviour you expect, but an easy way is to not calculate updates for cells on the edges.
So in generation_pass the loops should go from 1 till height-1.