I'm making a tic tac toe program. Right now, the two player option hasn't been created, but I will have no problem with that. My current issue is working on the bot function. Essentially, it's got 2 main ways of going about: botmove() where a random number is generated and it places its piece based on that number, of course testing that it is unoccupies, and smartmove() which is the function im struggling with. I've essentially given it an algoritm to test any win conditions (horizontal, vertical, and diagonal) and told it that, if it detects one, to place its piece to prevent loss. I have a " ..." and pause for a second to give it some time as well as to see whether or not its using smartmove() or botmove(). When you run the program, if the bot encounters a possible smartmove, it simply does nothing and moves onto the user's next term.
Here's the whole program, but main() and smartmove() are here for convenience.
Here's my main():
int main() {
char replaya;
replaya = 'y';
intro();
while (replaya == 'y' || replaya == 'Y') {
char friendorbota;
friendorbota = friendorbot();
if (friendorbota == 'f' || friendorbota == 'F') {
cout << "friend";
}
else if (friendorbota == 'b' || friendorbota == 'B') {
char arr[9] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
//1
placepiece(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//2
smartmove(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//3
placepiece(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//4
smartmove(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//5
placepiece(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//6
smartmove(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//7
placepiece(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//8
smartmove(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
//9
placepiece(arr);
if (determinewin(arr) == true) {
replaya = replay();
}
if (isFilled(arr) == true) {
replaya = replay();
}
}
cout << "\nThanks for playing!\n";
exit(0);
}
}
And my smartmove():
void smartmove(char arr[9]) {
this_thread::sleep_for(chrono::milliseconds(500));
cout << "\n\n . . . \n\n";
this_thread::sleep_for(chrono::milliseconds(500));
// Check if player has two in a row
for (int i = 0; i < 9; i += 3) {
if (arr[i] == 'X' && arr[i + 1] == 'X' && arr[i + 2] == ' ') {
arr[i + 2] = 'O';
return;
}
else if (arr[i] == 'X' && arr[i + 1] == ' ' && arr[i + 2] == 'X') {
arr[i + 1] = 'O';
return;
}
else if (arr[i] == ' ' && arr[i + 1] == 'X' && arr[i + 2] == 'X') {
arr[i] = 'O';
return;
}
}
// Check if player has two in a column
for (int i = 0; i < 3; i++) {
if (arr[i] == 'X' && arr[i + 3] == 'X' && arr[i + 6] == ' ') {
arr[i + 6] = 'O';
return;
}
else if (arr[i] == 'X' && arr[i + 3] == ' ' && arr[i + 6] == 'X') {
arr[i + 3] = 'O';
return;
}
else if (arr[i] == ' ' && arr[i + 3] == 'X' && arr[i + 6] == 'X') {
arr[i] = 'O';
return;
}
}
// Check if player has two in a diagonal
if (arr[0] == 'X' && arr[4] == 'X' && arr[8] == ' ') {
arr[8] = 'O';
}
else if (arr[0] == 'X' && arr[4] == ' ' && arr[8] == 'X') {
arr[4] = 'O';
}
else if (arr[0] == ' ' && arr[4] == 'X' && arr[8] == 'X') {
arr[0] = 'O';
}
else if (arr[2] == 'X' && arr[4] == 'X' && arr[6] == ' ') {
arr[6] = 'O';
}
else if (arr[2] == 'X' && arr[4] == ' ' && arr[6] == 'X') {
arr[4] = 'O';
}
else if (arr[2] == ' ' && arr[4] == 'X' && arr[6] == 'X') {
arr[2] = 'O';
}
else {
// Default to botmove() if no smart move is available
botmove(arr);
}
}
I've tested every function to ensure that everything is working fine, and I know that my main function could probably be organized a bit better but I wanted it as simple as possible while trying to solve this smartmove() issue. I've tested every function to ensure that everything is working fine other than smartmove(), so it seems like the only issue is with smartmove() or main() to my knowledge, although I've included all of the code in the link. And yes, I've done debugging by myself of every single section and both visual studio.
Related
#include <iostream>
using namespace std;
int main()
{
int tablica[9];
string inputromanum;
cout << "ROMAN: ";
cin >> inputromanum;
int maxindeks;
bool disablenextcomp = false;
int readysolution = 0;
maxindeks = inputromanum.length() - 1;{}{}
for (int i = 0; i <= maxindeks; i++)
{
if (inputromanum[i] == 'M' || inputromanum[i] == 'm')
{
tablica[i] = 1000;
}
if (inputromanum[i] == 'D' || inputromanum[i] == 'd')
{
tablica[i] = 500;
}
if (inputromanum[i] == 'C'|| inputromanum[i] == 'c')
{
tablica[i] = 100;
}
if (inputromanum[i] == 'L' || inputromanum[i] == 'l')
{
tablica[i] = 50;
}
if (inputromanum[i] == 'X' || inputromanum[i] == 'x')
{
tablica[i] = 10;
}
if (inputromanum[i] == 'V' || inputromanum[i] == 'v')
{
tablica[i] = 5;
}
if (inputromanum[i] == 'I' || inputromanum[i] == 'i')
{
tablica[i] = 1;
}
}
cout<<endl;
for(int i4 = 0; i4 <= maxindeks; i4++)
{
cout<<"tablica["<<i4<<"] = "<<tablica[i4]<<endl;
}
for (int i2 = 0; i2 <= maxindeks; i2++)
{
int i5 = i2 + 1;
if (i5 <= maxindeks)
{
//cout<<endl<<"tablica[i2 + 1] = "<<tablica[i2 + 1];
//cout<<endl<<"tablica[i2] = "<<tablica[i2];
//cout<<endl<<"tablica[i2 + 1] - tablica[i2] = "<<tablica[i2 + 1] - tablica[i2];
if (tablica[i2 + 1] - tablica[i2] > 0 && disablenextcomp == false)
{
//cout<<endl<<"readysolution + (tablica[i2 + 1] - tablica[i2]) = "<<readysolution + (tablica[i2 + 1] - tablica[i2])<<endl;
readysolution = readysolution + (tablica[i2 + 1] - tablica[i2]);
disablenextcomp = true;
}
else
{
if(disablenextcomp == false)
{
//cout<<endl<<"readysolution + tablica[i2] = "<<readysolution + tablica[i2]<<endl;
readysolution = readysolution + tablica[i2];
}
else
{
disablenextcomp = false;
}
}
}
else
{
if(disablenextcomp == false)
{
//cout<<endl<<endl<<"OSTATNI INDEKS";
//cout<<endl<<"tablica[i2] = "<<tablica[i2];
//cout<<endl<<"readysolution + tablica[i2] = "<<readysolution + tablica[i2];
readysolution = readysolution + tablica[i2];
}
}
i5++;
}
cout << endl << readysolution;
}
This is my program. made for decoding roman numerals into arabic ones. It works as intended in most cases, however, one of my colleagues found it to produce this error while inputting MMMCMXCVIII into the program:
*** stack smashing detected ***: terminated
It would refuse to work afterwards.
I wasn't able to find different numbers that would cause this error except MMMMMMMMMMM.
It seems to fail when the index of tablica array exceeds 10. I don't know why it does so, as i am a novice in c++. It should've outputted 3999 instead of the error appearing. The numbers it should process successfully should range from 1 to 5000.
Thanks to folks in the comments, I've found the cause.
The tablica[9] array is supposed to store 9 or less characters.
The length of the input (MMMCMXCVIII in this case) has more characters, therefore it makes the for loop responsible for storing values for each character to cause mentioned above error, as there are no remaining units to store the values in.
I've expanded the storage of tablica to 25 characters.
In modern C++ it is considered bad practice to use C-style arrays and index loops whenever you can avoid this. So, fo example you can rewrite first loop like this:
std::vector<int> tablica;
tablica.reserve(inputromanum.size()); // This line is not necessary, but it can help optimize memory allocations
for (char c : inputromanum)
{
if (c == 'M' || c == 'm')
{
tablica.push_back(1000);
}
if (c == 'D' || c == 'd')
{
tablica.push_back(500);
}
if (c == 'C'|| c == 'c')
{
tablica.push_back(100);
}
if (c == 'L' || c == 'l')
{
tablica.push_back(50);
}
if (c == 'X' || c == 'x')
{
tablica.push_back(10);
}
if (c == 'V' || c == 'v')
{
tablica.push_back(5);
}
if (c == 'I' || c == 'i')
{
tablica.push_back(1);
}
}
And you will avoid your issue completly. Something similar can be done with other loops too. This approach also has benefit of (somewhat) properly handling situations when input line has other symbols, which is not roman number. Try it on your version and you will see what I mean.
One more point. When you need to do something different depending of value of one variable, like you did with all those ifs. There is special statement in C/C++ for this: switch. So instead of those ifs you can do this:
std::vector<int> tablica;
tablica.reserve(inputromanum.size()); // This line is not necessary, but it can help optimize memory allocations
for (char c : inputromanum)
{
switch(c)
{
case 'M':
case 'm':
tablica.push_back(1000);
break;
case 'D':
case 'd':
tablica.push_back(500);
break;
case 'C':
case 'c':
tablica.push_back(100);
break;
case 'L':
case 'l':
tablica.push_back(50);
break;
case 'X':
case 'x':
tablica.push_back(10);
break;
case 'V':
case 'v':
tablica.push_back(5);
break;
case 'I':
case 'i':
tablica.push_back(1);
break;
}
}
This post is kind of a follow-up to my last post. To increase the efficiency of a minimax connect-4 AI algorithm, I decided to use alpha-beta pruning. This definitely helped with the long runtime of the program (which I previously believed to be an infinite recursion), but the AI is not working how I want it to.
The AI is simply choosing the next available empty spot to mark, even if it will lead to a loss.
I have tried increasing and decreasing the depth level, and made sure the function that checks for a winner actually works. Furthermore, I converted the 2d vector previously used for the board to a 1d vector, and updated other functions accordingly.
Any help on why the AI is behaving the way it is would be greatly appreciated.
Code:
#include <iostream>
#include <vector>
using namespace std;
bool isFull(std::vector<char>& grid) { //just checks if no empty spaces
for(int i = 0; i < 16; i++) {
if(grid[i] == '-') {
return false;
}
}
return true;
}
pair<bool, char> isWinner(std::vector<char>& grid, char aiMark, char hMark) {
pair<bool, char> temp; // the pair of: whether the game is over, and who won(if any.)
//'X' if AI wins, 'O' if human wins, '-' if tie/game not over.
//horizontal check
for (int i = 0; i < 16; i += 4) {
if (grid[i] == aiMark && grid[i + 1] == aiMark &&
grid[i + 2] == aiMark && grid[i + 3] == aiMark) {
temp.first = true;
temp.second = aiMark;
return temp;
}
else if (grid[i] == hMark && grid[i + 1] == hMark &&
grid[i + 2] == hMark && grid[i + 3] == hMark) {
temp.first = true;
temp.second = hMark;
return temp;
}
}
//vertical check
for (int i = 0; i < 4; i++) {
if (grid[i] == aiMark && grid[i + 4] == aiMark &&
grid[i + 8] == aiMark && grid[i + 12] == aiMark) {
temp.first = true;
temp.second = aiMark;
return temp;
}
else if (grid[i] == hMark && grid[i + 4] == hMark &&
grid[i + 8] == hMark && grid[i + 12] == hMark) {
temp.first = true;
temp.second = hMark;
return temp;
}
}
//diagonal checks
if (grid[0] == aiMark && grid[5] == aiMark &&
grid[10] == aiMark && grid[15] == aiMark) {
temp.first = true;
temp.second = aiMark;
return temp;
}
else if (grid[0] == hMark && grid[5] == hMark &&
grid[10] == hMark && grid[15] == hMark) {
temp.first = true;
temp.second = hMark;
return temp;
}
if (grid[3] == aiMark && grid[6] == aiMark &&
grid[9] == aiMark && grid[12] == aiMark) {
temp.first = true;
temp.second = aiMark;
return temp;
}
else if (grid[3] == hMark && grid[6] == hMark &&
grid[9] == hMark && grid[12] == hMark) {
temp.first = true;
temp.second = hMark;
return temp;
}
if (isFull(grid) == true) {
temp.first = true;
temp.second = '-';
return temp;
}
temp.first = false;
temp.second = '-';
return temp;
}
int minimax(std::vector<char>& grid, int depth, bool maxim,
char aiMark, char hMark, int al, int be) {
pair<bool, char> result = isWinner(grid, aiMark, hMark);
// result.first will be true if game is over, and result.second is:
// 'X' if ai wins, 'O' if human wins, '-' if game is not over or if it ends with tie
if (result.first != false || depth == 0) {
if (result.second == aiMark) {
return depth; // AI wins (maximizing)
}
else if (result.second == hMark) {
return -depth; // Human wins (minimizing)
}
else {
return 0; // Tie or depth = 0
}
}
else {
if (maxim == true) {
int best = INT_MIN;
for (int i = 0; i < 16; i++) {
if (grid[i] == '-') { // is space empty?
grid[i] = aiMark; // editing board
int score = minimax(grid, depth - 1, !maxim, aiMark, hMark, al, be); // call minimax with "new" board
best = max(best, score); // update max
grid[i] = '-'; // backtrack
al = best; // update alpha
if (al >= be) {
break; // pruning
}
}
}
return best; //return max score
}
else {
int worst = INT_MAX;
for (int i = 0; i < 16; i++) {
if (grid[i] == '-') {
grid[i] = hMark;
int score = minimax(grid, depth - 1, !maxim, aiMark, hMark, al, be);
worst = min(worst, score);
grid[i] = '-';
be = worst;
if (be <= al) { //same as the maximizing player but is minimizing instead
break;
}
}
}
return worst; //return min score
}
}
}
void bestMove(std::vector<char>& grid, char aiMark, char hMark) {
int best = INT_MIN; //best score for ai
int finalSpot = -1; //place where ai will put mark
pair<bool, char> result = isWinner(grid, aiMark, hMark); // explained in minimax function comments
if (result.first != false) {
return; // if game is supposed to be over
}
for (int i = 0; i < 16; i++) {
if (grid[i] == '-') {
grid[i] = aiMark;
int score = minimax(grid, 8, true, aiMark, hMark, INT_MIN, INT_MAX);
if (score > best) {
best = score;
finalSpot = i; // update best score and best spot
}
grid[i] = '-'; // backtrack
}
}
grid[finalSpot] = aiMark; // AI finally updates grid
return;
}
The algorithm can choose a losing move, because in bestMove(), you place an aiMark, then call minmax() with maxim set to true which will place a second aiMark in a row. The human does not play after the IA does.
Concerning alpha beta, you can also update alpha with : alpha = max(alpha, best), and the equivalent way with beta. The way you did is not wrong but not optimized, as the value of alpha can drop while it should only raise.
I think the best way to solve your game is to add a transposition table. It is a bit heavy to implement but IA will avoid studying twice the same position. You can first transform your code to a Negamax version which is easy and convenient.
These change the array that I print to the screen. direc is an input before this. However, when array[1][2] == '#', it still moves '#' to array[1][0].
if (array[1][1] == '#' && direc == 'A' || direc == 'a' ) {
array[1][1] = '_';
array[1][0] = '#';
}
else {
if (array[1][1] == '#' && direc == 'D' || direc == 'd' ) {
array[1][1] = '_';
array[1][2] = '#';
}
else {
if (array[1][2] == '#' && direc == 'A' || direc == 'a' ) {
array[1][1] = '#';
array[1][2] = '_';
}
}
}
You can either add parentheses, as already noted in the comments, like this
if (array[1][1] == '#' && (direc == 'A' || direc == 'a' )) {
Alternatively you could use std::tolower in which case you no longer nee
if (array[1][1] == '#' && std::tolower(direc) == 'a') {
You could still add extra parentheses if you are not comfortable that operator && is lower precedence than operator ==
(the full table of operator precedences can be seen here)
I'm having trouble with g++ producing this error code when I try to compile my code:
maze.h:16:29: error: array bound is not an integer constant before ‘]’ token
bool canMove(int m[mazeSize][mazeSize], int r, int c);
Now, I have already done some research into this error and it seems to be causes by the array size not being known at compile time. I have tried making the array constant, but that ends up causing more errors later on as the array is reassigned later on in the code and produces this error:
maze.cpp: In member function ‘int Maze::startMazeGen()’:
maze.cpp:185:15: error: assignment of read-only location ‘maze[i][j]’
maze[i][j] = 1;
^
I have also seen people mention that it would just be easier to work with vectors instead, but I'm also having issues with trying to repurpose the code to work with vectors instead of arrays.
Here's the rest of my code:
movement.h
#pragma once
#include <iostream>
#include <curses.h>
#ifndef MOVEMENT_H
#define MOVEMENT_H
class Movement
{
public:
static const int playerX = 2; // sets player starting position
static const int playerY = 2;
};
#endif
movement.cpp
#include <iostream>
#include <curses.h>
#include <ctime>
#include "maze.h"
//#include "movement.h"
bool running = true;
int playerX = 2;
int playerY = 2;
//Maze::maze Maze::mazeGen;
//int Maze::mazeGen.Maze::maze::generateMaze::maze(int m[Maze::mazeSize]
[Maze::mazeSize], int r, int c);
// Detect Char input
// and move player in direction
void getUserInput()
{
char userInput = getch();
if (userInput == 'w') {
int playerY2 = playerY - 1;
if (Maze::maze[playerY2][playerX] == ' ') {
Maze::maze[playerY][playerX] = ' ';
playerY--;
Maze::maze[playerY][playerX] = 'x';
}
}
if (userInput == 'a') {
int playerX2 = playerX - 1;
if (Maze::maze[playerY][playerX2] == ' ') {
Maze::maze[playerY][playerX] = ' ';
playerX--;
Maze::maze[playerY][playerX] = 'x';
}
}
if (userInput == 's') {
int playerY2 = playerY + 1;
if (Maze::maze[playerY2][playerX] == ' ') {
Maze::maze[playerY][playerX] = ' ';
playerY++;
Maze::maze[playerY][playerX] = 'x';
}
}
if (userInput == 'd') {
int playerX2 = playerX + 1;
if (Maze::maze[playerY][playerX2] == ' ') {
Maze::maze[playerY][playerX] = ' ';
playerX++;
Maze::maze[playerY][playerX] = 'x';
}
}
}
// Main game update
// Runs through all functions required
void update()
{
getUserInput();
clear();
Maze::generateMaze;
refresh();
}
//
//
/*int main()
{
// Initate nCurses display
initscr();
while (true) {
update();
}
// End nCurses display
endwin();
return 0;
}*/
maze.h
#pragma once
// MAZE.h
#include <iostream>
#include <ctime>
#ifndef MAZE_H
#define MAZE_H
extern int r;
extern int c;
extern int mazeSize; //number can be changed to make some big sweaty mazes making it an even number makes it act a bit weird sometimes so its better to use an odd number
extern int maze[mazeSize][mazeSize];
class Maze
{
public:
int blockedSquare = 1;
void move(int m[mazeSize][mazeSize], int &r, int &c);
bool canMove(int m[mazeSize][mazeSize], int r, int c);
void solve(int m[mazeSize][mazeSize], int &r, int &c);
bool canSolve(int m[mazeSize][mazeSize], int r, int c);
void generateMaze(int m[mazeSize][mazeSize], int r, int c);
int findStart();
void printMaze(int m[mazeSize][mazeSize]);
int startMazeGen();
};
#endif
maze.cpp
#include <iostream>
#include <ctime>
#include <vector>
#include "maze.h"
bool foundExit = false;
int mazeSize = 31;
int maze[mazeSize][mazeSize] = { 0 };
void Maze::generateMaze(int const m[mazeSize][mazeSize], int r, int c)
{
bool made = false;
while (made == false)
{
if (c == mazeSize - 1)
foundExit = true;
if (canSolve(m, r, c))
{
solve(m, r, c);
}
else if (canMove(m, r, c))
{
m[r][c] = 2; //2 means you can't move from that square, setting any lower stops maze from being made
move(m, r, c); //move to first open space that can be found
}
else
made = true;
}
}
void Maze::move(int m[mazeSize][mazeSize], int &r, int &c)
{
if (m[r][c + 1] == 0)
c++;
else if (m[r + 1][c] == 0)
r++;
else if (m[r][c - 1] == 0)
c--;
else if (m[r - 1][c] == 0)
r--;
else
generateMaze(maze, r, c); //if maze cant be solved it generates a new one so the player doesnt have something that is impossible to solve
}
bool Maze::canMove(int m[mazeSize][mazeSize], int r, int c) //if there is an adjacent zero space, return true
{
if (m[r][c + 1] == 0)
return true;
else if (m[r + 1][c] == 0)
return true;
else if (m[r][c - 1] == 0)
return true;
else if (m[r - 1][c] == 0)
return true;
else
return false;
}
void Maze::solve(int m[mazeSize][mazeSize], int &r, int &c) //solves maze through with dijkstras algorithmto ensure it can be solved
{
bool foundSolution = false;
while (foundSolution == false)
{
int direction = (1 + rand() % 4) * 3;
switch (direction)
{
case 3:
if (c + 1 <= mazeSize - 1 && m[r][c + 2] == blockedSquare && m[r - 1][c + 1] == blockedSquare && m[r + 1][c + 1] == blockedSquare && m[r][c + 1] == blockedSquare)
{
if (c == mazeSize - 2 && foundExit == true)
; //do nothing
else
{
c++;
foundSolution = true;
}
}
break;
case 6:
if (r + 1 <= mazeSize - 2 && m[r + 2][c] == blockedSquare && m[r + 1][c + 1] == blockedSquare && m[r + 1][c - 1] == blockedSquare && m[r + 1][c] == blockedSquare && c != 0 && c != mazeSize - 1)
{
r++;
foundSolution = true;
}
break;
case 9:
if (c - 1 >= 0 && m[r][c - 2] == blockedSquare && m[r - 1][c - 1] == blockedSquare && m[r + 1][c - 1] == blockedSquare && m[r][c - 1] == blockedSquare && c - 1 != 0)
{
c--;
foundSolution = true;
}
break;
case 12:
if (r - 1 >= 1 && m[r - 2][c] == blockedSquare && m[r - 1][c + 1] == blockedSquare && m[r - 1][c - 1] == blockedSquare && m[r - 1][c] == blockedSquare && c != 0 && c != mazeSize - 1)
{
r--;
foundSolution = true;
}
break;
}
}
m[r][c] = 0;
}
bool Maze::canSolve(int m[mazeSize][mazeSize], int r, int c) //if an adjacent square can be moved to, return true
{
bool solvable = false;
if (r <= mazeSize - 3 && m[r + 2][c] == blockedSquare && m[r + 1][c + 1] == blockedSquare && m[r + 1][c - 1] == blockedSquare && m[r + 1][c] == blockedSquare && c != 0 && c != mazeSize - 1) //if adjacent space can be moved to
{
solvable = true;
}
else if (c <= mazeSize - 2 && m[r][c + 2] == blockedSquare && m[r - 1][c + 1] == blockedSquare && m[r + 1][c + 1] == blockedSquare && m[r][c + 1] == blockedSquare)
{
if (c == mazeSize - 2 && foundExit == true)
; //do nothing
else
{
solvable = true;
}
}
else if (r >= 2 && m[r - 2][c] == blockedSquare && m[r - 1][c + 1] == blockedSquare && m[r - 1][c - 1] == blockedSquare && m[r - 1][c] == blockedSquare && c != 0 && c != mazeSize - 1) //if not on extreme left or right
{
solvable = true;
}
else if (c >= 1 && m[r][c - 2] == blockedSquare && m[r - 1][c - 1] == blockedSquare && m[r + 1][c - 1] == blockedSquare && m[r][c - 1] == blockedSquare && c - 1 != 0)
{
solvable = true;
}
return solvable;
}
int Maze::findStart()
{
return 1 + rand() % (mazeSize - 2);
}
void Maze::printMaze(int m[mazeSize][mazeSize])
{
std::cout << std::endl;
for (int i = 0; i < mazeSize; ++i) {
for (int j = 0; j < mazeSize; ++j)
{
switch (m[i][j])
{
case 0:
std::cout << " ";
break;
case 1:
std::cout << "▓▓";
break;
case 2:
std::cout << " ";
break;
case 3:
std::cout << " ";
break;
}
}
std::cout << std::endl;
}
}
int Maze::startMazeGen()
{
srand(time(0));
for (int i = 0; i < mazeSize; ++i)
for (int j = 0; j < mazeSize; ++j)
maze[i][j] = 1;
int r = findStart();
//int r = 0;
int c = 0;
maze[r][c] = 0;
generateMaze(maze, r, c);
maze[r][c] = 2;
printMaze(maze);
std::cout << "Press enter to continue ...";
std::cin.get();
}
The purpose of this code is to randomly generate a maze, solve it, and then print it to the screen if it can be solved. If the maze can't be solved, it keeps generating a new one until it can be solved.I aim to make this work with the movement code so that the user can navigate the maze.
Any help is appreciated on this issue. Thank you!
"Now, I have already done some research into this error and it seems to be causes by the array size not being known at compile time. I have tried making the array constant, but that ends up causing more errors later on as the array is reassigned later on in the code"
You're conflating two things here, the array and the array size.
The array size should be a a compile-time constant. Since you're assigning to the array, the array elements shouldn't be const at all.
const int arrSize = 3;
int arr[arrSize][arrSize];
I am in need of help for this code that i am working on for a assignment. I am have the issue where if i have any X's on the board that is either in the left 2 columns it will display a X in the row above. I used my debugger and it seems that it is trying to access something outside the array bounds, but it shouldnt be. any advice on how to do this?
#include <iostream>
using namespace std;
void printTTT(char a[3][3]);
void insertX(/*PASS BY REFERENCE*/);
void insertO(char (&arr)[3][3]);
void checkForWin(/*PASS BY REFERENCE*/); // IGNORE THIS FOR NOW
int main() {
char TTTarray[3][3] = { { 'X','-','-' },
{ '-','-','-' },
{ 'X','-','-' } };
//char TTTarray[3][3] = { {'-','X','-'},
// {'-','X','-'},
// {'-','-','O'}};
//char TTTarray[3][3] = { {'-','-','-'},
// {'-','X','-'},
// {'-','O','-'}};
//char TTTarray[3][3] = { {'X','-','X'},
// {'-','-','-'},
// {'O','-','-'}};
//char TTTarray[3][3] = { {'X','-','X'},
// {'O','X','-'},
// {'O','-','O'}};
//insertX(/*CALL*/);
//OR
insertO(TTTarray);
printTTT(TTTarray);
/*****************
I have included the declaratoin of the array, initialized to - for each spot.
The '-' represents an empty position. You should fill it with either a
capital 'O' or a capital 'X'. I have also included a number of initialized arrays
to test; just comment out the ones you don't want for that moment
*****************/
return 0;
}
void printTTT(char a[3][3])
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cout << a[i][j];
}
cout << endl;
}
}
void insertX(/*PASS BY REFERENCE*/) {
}
void insertO(char (&arr)[3][3])
{
int x1x;
int x1y;
//int x2x;
//int x2y;
for (int i = 0; i < 3; i++)
{
int go = 0;
for (int j = 0; j < 3; j++)
{
if (arr[i][j] == '-')
{
x1x = i;
x1y = j;
// looking for 2 x's for the block lol
if (x1x == 0 && go == 0)
{
if (arr[x1x][x1y + 1] == 'X' && arr[x1x][x1y + 2] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x][x1y - 1] == 'X' && arr[x1x][x1x + 1] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x][x1y - 1] == 'X' && arr[x1x][x1x - 2] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
}
if (x1x == 1 && go == 0)
{
if (arr[x1x][x1y + 1] == 'X' && arr[x1x][x1y + 2] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x][x1y - 1] == 'X' && arr[x1x][x1x + 1] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x][x1y - 1] == 'X' && arr[x1x][x1x - 2] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
}
if (x1x == 2 && go == 0)
{
if (arr[x1x][x1y + 1] == 'X' && arr[x1x][x1y + 2] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x][x1y - 1] == 'X' && arr[x1x][x1x + 1] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x][x1y - 1] == 'X' && arr[x1x][x1x - 2] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
}
if (x1y == 0 && go == 0)
{
if (arr[x1x + 1][x1y] == 'X' && arr[x1x + 2][x1y] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x - 1][x1y] == 'X' && arr[x1x + 1][x1x] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x - 1][x1y] == 'X' && arr[x1x - 2][x1x] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
}
if (x1y == 1 && go == 0)
{
if (arr[x1x + 1][x1y] == 'X' && arr[x1x + 2][x1y] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x - 1][x1y] == 'X' && arr[x1x + 1][x1x] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x - 1][x1y] == 'X' && arr[x1x - 2][x1x] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
}
if (x1y == 2 && go == 0)
181,1-8 83%
{
if (arr[x1x + 1][x1y] == 'X' && arr[x1x + 2][x1y] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x - 1][x1y] == 'X' && arr[x1x + 1][x1x] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
if (arr[x1x - 1][x1y] == 'X' && arr[x1x - 2][x1x] == 'X')
{
arr[i][j] = 'O';
go = 1;
}
}
}
}
}
}
Take a look at these lines from your insertD function:
if (x1x == 0 && go == 0)
{
if (arr[x1x][x1y + 1] == 'X' && arr[x1x][x1y + 2] == 'X')
In this case you have checked that x1x is zero, but you haven't checked x1y. So in this case you will go out of bounds if x1y is non-zero.
A couple of lines below you have
if (arr[x1x][x1y - 1] == 'X' && arr[x1x][x1x + 1] == 'X')
This will go out of bounds too, when x1y is zero.
You need to add more checks, or rethink the logic.