Code compiles, however crashes after start(rot13) [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So, I have been fiddling around with a code for a ctf competition. However, every time I run the actual console application, it keeps crashing. Could someone please explain to me why. Thank you so much in advance.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int lowerConvert(char x)
{
int y;
if (x == 'a')
y = 1;
if (x == 'b')
y = 2;
if (x == 'c')
y = 3;
if (x == 'd')
y = 4;
if (x == 'e')
y = 5;
if (x == 'f')
y = 6;
if (x == 'g')
y = 7;
if (x == 'h')
y = 8;
if (x == 'i')
y = 9;
if (x == 'j')
y = 10;
if (x =='k')
y = 11;
if (x == 'l')
y = 12;
if (x == 'm')
y = 13;
if (x == 'n')
y = 14;
if (x == 'o')
y = 15;
if (x == 'p')
y = 16;
if (x == 'q')
y = 17;
if (x == 'r')
y = 18;
if (x == 's')
y = 19;
if (x == 't')
y = 20;
if (x == 'u')
y = 21;
if (x == 'v')
y = 22;
if (x == 'w')
y = 23;
if (x == 'x')
y = 24;
if (x == 'y')
y = 25;
if (x == 'z')
y = 26;
return y;
}
int upperConvert(char x)
{
int y;
if (x == 'A')
y = 27;
if (x == 'B')
y = 28;
if (x == 'C')
y = 29;
if (x == 'D')
y = 30;
if (x == 'E')
y = 31;
if (x == 'F')
y = 32;
if (x == 'G')
y = 33;
if (x == 'H')
y = 34;
if (x == 'I')
y = 35;
if (x == 'J')
y = 36;
if (x == 'K')
y = 37;
if (x == 'L')
y = 38;
if (x == 'M')
y = 39;
if (x == 'N')
y = 40;
if (x == 'O')
y = 41;
if (x == 'P')
y = 42;
if (x == 'Q')
y = 43;
if (x == 'R')
y = 44;
if (x == 'S')
y = 45;
if (x == 'T')
y = 46;
if (x == 'U')
y = 47;
if (x == 'V')
y = 48;
if (x == 'W')
y = 49;
if (x == 'X')
y = 50;
if (x == 'Y')
y = 51;
if (x == 'Z')
y = 52;
return y;
}
char lowerBack(int x)
{
char y;
if (x == 1)
y = 'a';
else if (x == 2)
y = 'b';
else if (x == 3)
y = 'c';
else if (x == 4)
y = 'd';
else if (x == 5)
y = 'e';
else if (x == 6)
y = 'f';
else if (x == 7)
y = 'g';
else if (x == 8)
y = 'h';
else if (x == 9)
y = 'i';
else if (x == 10)
y = 'j';
else if (x == 11)
y = 'k';
else if (x == 12)
y = 'l';
else if (x == 13)
y = 'm';
else if (x == 14)
y = 'n';
else if (x == 15)
y = 'o';
else if (x == 16)
y = 'p';
else if (x == 17)
y = 'q';
else if (x == 18)
y = 'r';
else if (x == 19)
y = 's';
else if (x == 20)
y = 't';
else if (x == 21)
y = 'u';
else if (x == 22)
y = 'v';
else if (x == 23)
y = 'w';
else if (x == 24)
y = 'x';
else if (x == 25)
y = 'y';
else if (x == 26)
y = 'z';
return y;
}
char upperBack(int x)
{
char y;
if (x == 27)
y = 'A';
if (x == 28)
y = 'B';
if (x == 29)
y = 'C';
if (x == 30)
y = 'D';
if (x == 31)
y = 'E';
if (x == 32)
y = 'F';
if (x == 33)
y = 'G';
if (x == 34)
y = 'H';
if (x == 35)
y = 'I';
if (x == 36)
y = 'J';
if (x == 37)
y = 'K';
if (x == 38)
y = 'L';
if (x == 39)
y = 'M';
if (x == 40)
y = 'N';
if (x == 41)
y = 'O';
if (x == 42)
y = 'P';
if (x == 43)
y = 'Q';
if (x == 44)
y = 'R';
if (x == 45)
y = 'S';
if (x == 46)
y = 'T';
if (x == 47)
y = 'U';
if (x == 48)
y = 'V';
if (x == 49)
y = 'W';
if (x == 50)
y = 'X';
if (x == 51)
y = 'Y';
if (x == 52)
y = 'Z';
return y;
}
void primaryRot13()
{
cout << "Please enter name of file to be decrypted: ";
string name;
getline(cin, name);
name += ".txt";
ifstream file;
ofstream write;
file.open(name);
string message;
file >> message;
int converted[9999999];
char reconvert[9999999];
for (int i = 0; i < message.length();++i)
{
if (message[i] == 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9)
message[i] += 53;
if (message[i] == 'a' || 'b' || 'c' || 'd' || 'e' || 'f' || 'g' || 'h' || 'i' || 'j' || 'k' || 'l' || 'm' || 'n' || 'o' || 'p' || 'q' || 'r' || 's' || 't' || 'u' || 'v' || 'w' || 'x' || 'y' || 'z')
converted[i] = lowerConvert(message[i]);
converted[i] += 13;
if (converted[i] > 26)
converted[i] -= 26;
if (message[i] == 'A' || 'B' || 'C' || 'D' || 'E' || 'F' || 'G' || 'H' || 'I' || 'J' || 'K' || 'L' || 'M' || 'N' || 'O' || 'P' || 'Q' || 'R' || 'S' || 'T' || 'U' || 'V' || 'W' || 'X' || 'Y' || 'Z')
converted[i] = upperConvert(message[i]);
converted[i] += 13;
if (converted[i] > 52)
converted[i] -= 26;
}
for (int i = 0; i < message.length(); ++i)
{
if (converted[i] == 52 || 53 || 54 || 55 || 56 || 57 || 58 || 59 || 60 || 61){
reconvert[i] = converted[i] - 53;
continue;
}
if (converted[i] < 27){
reconvert[i] = lowerBack(converted[i]);
continue;
}
if (converted[i] < 51){
reconvert[i] = upperBack(converted[i]);
continue;
}
write.open("decode");
write << reconvert[i];
}
}
EDIT AND FINAL SOLUTION
Several years later, I am here to repost. What I ended up doing was simply adding the desired amount to the character code, then if it is greater than the upper limit for that set, I subtracted 26 in order to reset. I also ended up using the vector instead, which did solve my issue of crashing. Now I can happily rot13 all day long :) All without the myriad of if statements.

Table Lookup
First, an introduction to table or array look ups.
Given a character array:
static const char letters[] = "abcdefghijklmnopqrstuvwxyz";
The index of 'a' is 0, 'b' is 1, ..., 'z' is 25.
The array can be searched for a letter. The index of the letter can be it's number. In your case, it would be the index + 1.
Example:
static const unsigned int letter_quantity = sizeof(letters) / sizeof(letters[0]);
unsigned int index = 0;
for (index = 0; index < letter_quantity; ++i)
{
if (letters[i] == x)
{
break;
}
}
At the end of the loop statement, the index variable will be the position of the character in x or the length of the array (if not found).
Modulo Arithmetic
Modulo arithmetic, using the % operator, returns the remainder. It has the behavior of wrapping around. This can be used with the array.
unsigned int new_char_index = index + 13; // We may have gone past the array.
new_char_index = new_char_index % letter_quantity; // Wrap around.
The New ROT13 Character
The converted character can be found by using the new_char_index as the index into the array.
char rot13 = letters[new_char_index];
Covering all the characters
The remaining uppercase characters can be added to the array to account for all the letters. Other symbols can be added also.
All this without any if statements.

You're allocating two static arrays of 9999999 elements on the stack.
If an int is 32 bits and a char is 8 bits on your system, then that's 48MB of memory. That's simply too much for the stack.
Try allocating your arrays dynamically instead, i.e. using std::vector:
std::vector<int> converted(9999999);
std::vector<char> reconvert(9999999);

Related

Mouse events not working as they should in functions

I am displaying a card stack and need to know the exact pinpoints of the pixels so I mapped out a function that should return whatever LMB location was at pressed time. The issue with this is that for some reason I can no longer see the cards.
I tried making the function a class member of Game, but then the mouse logic doesn't work at all. I still had MyMouse M; declared but its like the code was just ignored completely. I know how to overload functions and yet this just seems to defy logic.
Function for MouseLogic();
void MouseLogic() {
Game G;
Coordinates C;
MyMouse M;
G.PrintLL(10, 25, G.start_user);
G.PrintLL(10, 10, G.start_cpu);
while (1) {
M.ReadMouseInput();
switch (M.InputRecord.EventType)
{
case MOUSE_EVENT: // mouse input
if (M.InputRecord.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
{
int x = M.InputRecord.Event.MouseEvent.dwMousePosition.X;
int y = M.InputRecord.Event.MouseEvent.dwMousePosition.Y;
cout << GetCardNumber(x, y);
}
}
}
}
Function for GetCardNumber
int GetCardNumber(int x, int y)
{
if ((x >= 10 && x <= 23) && (y >= 10 && y <= 25))
return 1;
else if ((x >= 41 && x <= 54) && (y >= 10 && y <= 25))
return 2;
else if ((x >= 72 && x <= 85) && (y >= 10 && y <= 25))
return 3;
else if ((x >= 45 && x <= 60) && (y >= 10 && y <= 25))
return 4;
else if ((x >= 78 && x <= 91) && (y >= 10 && y <= 25))
return 5;
else if ((x >= 10 && x <= 23) && (y >= 25 && y <= 40))
return 6;
else if ((x >= 41 && x <= 54) && (y >= 25 && y <= 40))
return 7;
else if ((x >= 72 && x <= 85) && (y >= 25 && y <= 40))
return 8;
else if ((x >= 45 && x <= 60) && (y >= 25 && y <= 40))
return 9;
else if ((x >= 78 && x <= 91) && (y >= 25 && y <= 40))
return 10;
else
return 0;
}
This seemed to work for anyone wondering! I just had to pass the class as an argument for some reason. Would still love an explanation for the logic behind this.
void MouseLogic(Game G) {
Coordinates C;
MyMouse M;
G.PrintLL(10, 25, G.start_user);
G.PrintLL(10, 10, G.start_cpu);
while (1) {
M.ReadMouseInput();
switch (M.InputRecord.EventType)
{
case MOUSE_EVENT: // mouse input
if (M.InputRecord.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
{
int x = M.InputRecord.Event.MouseEvent.dwMousePosition.X;
int y = M.InputRecord.Event.MouseEvent.dwMousePosition.Y;
cout << GetCardNumber(x, y);
}
}
}
}

tictaktoe Array bound overflow

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.

getline() isn't working in code

Yesterday I started developing a encrypting machine, that works like a Caesar cipher. You put a message (e.g., HELLO), choose a key value (e.g., 3) and the result is KHOOR (3 letters forward).
The problem is that, if I use "cin >> msg;" I can only codify one word. If I use "getline (cin, msg);", the code doesn't work. Maybe it's a simple problem, but I can't solve it... :(
string msg;
int a, b, i, key_value;
char c;
cout << "WRITE YOUR MESSAGE:" << endl;
cin >> msg; //HERE IS THE PROBLEM!!!
system ("cls");
cout << "PUT A KEY VALUE:" << endl;
cin >> key_value;
system ("cls");
cout << "THE CODIFIED MESSAGE IS:" << endl;
for (i=0; i < msg.length(); i++) {
if (msg[i] == 'A') a = 1;
if (msg[i] == 'B') a = 2;
if (msg[i] == 'C') a = 3;
if (msg[i] == 'D') a = 4;
if (msg[i] == 'E') a = 5;
if (msg[i] == 'F') a = 6;
if (msg[i] == 'G') a = 7;
if (msg[i] == 'H') a = 8;
if (msg[i] == 'I') a = 9;
if (msg[i] == 'J') a = 10;
if (msg[i] == 'K') a = 11;
if (msg[i] == 'L') a = 12;
if (msg[i] == 'M') a = 13;
if (msg[i] == 'N') a = 14;
if (msg[i] == 'O') a = 15;
if (msg[i] == 'P') a = 16;
if (msg[i] == 'Q') a = 17;
if (msg[i] == 'R') a = 18;
if (msg[i] == 'S') a = 19;
if (msg[i] == 'T') a = 20;
if (msg[i] == 'U') a = 21;
if (msg[i] == 'V') a = 22;
if (msg[i] == 'W') a = 23;
if (msg[i] == 'X') a = 24;
if (msg[i] == 'Y') a = 25;
if (msg[i] == 'Z') a = 26;
b = a + key_value;
if (b > 26) b -= 26;
if (b == 1) c = 'A';
if (b == 2) c = 'B';
if (b == 3) c = 'C';
if (b == 4) c = 'D';
if (b == 5) c = 'E';
if (b == 6) c = 'F';
if (b == 7) c = 'G';
if (b == 8) c = 'H';
if (b == 9) c = 'I';
if (b == 10) c = 'J';
if (b == 11) c = 'K';
if (b == 12) c = 'L';
if (b == 13) c = 'M';
if (b == 14) c = 'N';
if (b == 15) c = 'O';
if (b == 16) c = 'P';
if (b == 17) c = 'Q';
if (b == 18) c = 'R';
if (b == 19) c = 'S';
if (b == 20) c = 'T';
if (b == 21) c = 'U';
if (b == 22) c = 'V';
if (b == 23) c = 'W';
if (b == 24) c = 'X';
if (b == 25) c = 'Y';
if (b == 26) c = 'Z';
cout << c;
}
So your code works fine: http://ideone.com/lBhD78
If you're trying to accept more than 1 word the simple extraction operator will not work however. Which is probably what you're asking about. In this case you will want to use getline. Like this for instance:
getline(cin, msg, '\n');
So I'm not certain what you're complaining about, however this could be much improved by:
Being case-insensitive
Only modifying alpha-characters
You could accomplish this by doing something like:
transform(cbegin(msg), cend(msg), ostream_iterator<char>(cout), [&](unsigned char i){
if(isalpha(i)) {
const auto a = islower(i) ? 'a' : 'A';
i = (i - a + key_value) % 26 + a;
}
return i; });
I've written a Live Example complete with getline.
You have to be carefull to write questions.
BUT, without being clear what you mean, the answer is:
When you read cin>>s, by default, you are considering the data are separated by "white spaces". So, it skips spaces and read the string until a new space or end of input.
If you have problems with getline, probably the problem is before the code you are shown. If you read a value with, for example, cin>>integer, you push newline key at the end of the input, but this character is still in the stream. If the following line in your code es getline, probably you will read an empty line.
In the first item you find why you current code works, in the second one, why your getline-version doesn't.

'C' Program: multidimensional array issue

Please help me figure this out, I have tested it and tested it and re-read and re-wrote for the past 11 hours and I give up. I found a working code that someone else wrote, but it still doesn't explain to me why his works and mine doesn't because the problem that I am having works on his but not on mine
Got it people, code edited for anyone who has had a similiar problem...
The original code that I had is here http://pastebin.com/h7fXHKzf
the problem I was having was that it kept hanging up on the if(board[x][y - 1] == '.') checks.
Spoke too soon....The program will sometimes crash...it's rare but has crashed 3x in a row before...most of the time when I run it everything works.
// Chapter 8 Programming Project #9
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 10
#define PATH_SIZE ((int) (sizeof(brd_path)))
#define ROW_SIZE ((int) (sizeof(board) / sizeof(board[0])))
int main(void)
{
char board[SIZE][SIZE] = {};
char brd_path[25] = {'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z'};
// 0 = Up, 1 = Down, 2 = Left, 3 = Right
bool path_dir_chk[4] = {false};
bool blocked = false;
unsigned short i, j, x = 0, y = 0;
// Generate a random number
srand((unsigned) time(NULL));
int dir = rand() % 4;
// Set all positions of board to '.'
for (x = 0; x < ROW_SIZE; x++) {
for (y = 0; y < ROW_SIZE; y++)
board[x][y] = '.';
}
x = 0;
y = 0;
board[0][0] = 'A';
// Generate the path
while (blocked != true && i != PATH_SIZE) {
for (i = 0; i < PATH_SIZE;) {
// Reset path_dir_chk values if empty
for (j = 0; j < 4; j++) {
if (board[x][y - 1] == '.')
path_dir_chk[0] = false;
if (board[x][y + 1] == '.')
path_dir_chk[1] = false;
if (board[x - 1][y] == '.')
path_dir_chk[2] = false;
if (board[x + 1][y] == '.')
path_dir_chk[3] = false;
}
// Check the direction and replace that char
switch (dir) {
case 0: if ((y - 1) >= 0 && board[x][y - 1] == '.') {
board[x][--y] = brd_path[i];
path_dir_chk[0] = true;
printf("I is now: %d\n", ++i);
} break;
case 1: if ((y + 1) >= 0 && board[x][y + 1] == '.') {
board[x][++y] = brd_path[i];
path_dir_chk[1] = true;
printf("I is now: %d\n", ++i);
} break;
case 2: if ((x - 1) >= 0 && board[x - 1][y] == '.') {
board[--x][y] = brd_path[i];
path_dir_chk[2] = true;
printf("I is now: %d\n", ++i);
} break;
case 3: if ((x + 1) >= 0 && board[x + 1][y] == '.') {
board[++x][y] = brd_path[i];
path_dir_chk[3] = true;
printf("I is now: %d\n", ++i);
} break;
}
// if all path's are true exit
if (path_dir_chk[0] == true &&
path_dir_chk[1] == true &&
path_dir_chk[2] == true &&
path_dir_chk[3] == true)
blocked = true;
// Reset the random direction
dir = rand() % 4;
}
}
// Print the board
for (x = 0; x < ROW_SIZE; x++) {
for (y = 0; y < ROW_SIZE; y++)
printf("%c ", board[x][y]);
printf("\n");
}
return 0;
}
OK I have made changes to reflect what I have so far, no it is printing 'I is now:' numbers 1 - 25 and then it starts over but it stops on 12 the second time around and freezes into some kind of loop
Below is the working code I found online, you can compare the two and see the similarity's but the lines of code on his that are exactly like mine do not work on mine.....
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROWS 10
#define COLS 10
int main (void)
{
int i, j, k, direction;
char board[ROWS][COLS];
const char letters[] = {'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z'};
srand ((unsigned) time(NULL));
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
board[i][j] = '.';
i = 0;
j = 0;
k = 1;
//set array[0][0] to first element
board[i][j] = letters[0];
while (k < 26) {
direction = rand() % 4;
if (board[i][j] == '.')
board[i][j] = letters[k++];
if ((board[i][j + 1] != '.' || j == ROWS - 1 )&&
(board[i + 1][j] != '.' || i == COLS -1) &&
(board[i - 1][j] != '.' || i == 0) &&
(board[i][j - 1] != '.' || j == 0))
break;
switch (direction) {
case 0: if (j < ROWS - 1 && board[i][j + 1] == '.'){ //move right
j++;
break; }
case 1: if (i < COLS -1 && board[i + 1][j] == '.') { //move down
i++;
break; }
case 2: if (i > 0 && board[i - 1][j] == '.'){ //move up
i--;
break; }
case 3: if (j > 0 && board[i][j - 1] == '.') { //move left
j--;
break; }
}
}
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++)
printf ("%4c", board[i][j]);
printf ("\n");
}
return 0;
}
You aren't setting x and y back to 0 after this code
for (x = 0; x < ROW_SIZE; x++) {
for (y = 0; y < ROW_SIZE; y++)
board[x][y] = '.';
}
Thus x and y will start at 10. Also you aren't range checking x and y, which means that x and y might wander off the board.
This code
if ((board[x][y - 1] != '.' || y - 1 < 0) &&
(board[x][y + 1] != '.' || y + 1 > ROW_SIZE) &&
(board[x - 1][y] != '.' || x - 1 < 0) &&
(board[x + 1][y] != '.' || x + 1 > ROW_SIZE))
should be this
if ((y - 1 < 0 || board[x][y - 1] != '.') &&
(y + 1 >= ROW_SIZE || board[x][y + 1] != '.') &&
(x - 1 < 0 || board[x - 1][y] != '.') &&
(x + 1 >= ROW_SIZE || board[x + 1][y] != '.'))
There are two subtle differences.
First y+1 and x+1 are not allowed to be equal to ROW_SIZE, since ROW_SIZE is 10, but the valid array indices are 0 to 9.
Second, order is important. When evaluating a logical OR, the left side is evaluated first, and if it's true, then the right side is not evaluated. This is important, since on some machines, even reading outside of the array bounds will cause a crash.
for (x = 0; x < ROW_SIZE; x++) {
for (y = 0; y < ROW_SIZE; y++)
board[x][y] = '.';
}
After the initialization you are not resetting the value of x and y. While value of X= ROW_SIZE, you are trying to access board[x + 1][y] and board[x][y + 1].
x = 0;
y = 0;
Thanks user3386109 your input was invaluable as was the rest of y'alls help I appreciate it, the working code is below :)
// Chapter 8 Programming Project #9
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 10
#define PATH_SIZE 25
#define ROW_SIZE ((int) (sizeof(board) / sizeof(board[0])))
int main(void)
{
char board[SIZE][SIZE];
// 0 = Up, 1 = Down, 2 = Left, 3 = Right
unsigned short i = 0, x, y;
// Generate a random number
srand((unsigned) time(NULL));
int dir = rand() % 4;
// Set all positions of board to '.'
for (x = 0; x < ROW_SIZE; x++) {
for (y = 0; y < ROW_SIZE; y++)
board[x][y] = '.';
}
x = 0;
y = 0;
board[0][0] = 'A';
// Generate the path
for (i = 0; i < PATH_SIZE;) {
// Check that the last character has not been cornered
if ((board[x][y - 1] != '.' || y - 1 < 0) &&
(board[x][y + 1] != '.' || y + 1 > ROW_SIZE) &&
(board[x - 1][y] != '.' || x - 1 < 0) &&
(board[x + 1][y] != '.' || x + 1 > ROW_SIZE))
break;
// Check the direction and replace that char
switch (dir) {
case 0: if ((y - 1) >= 0
&& board[x][y - 1] == '.') {
board[x][--y] = i + 'B';
++i;
} break;
case 1: if ((y + 1) < ROW_SIZE
&& board[x][y + 1] == '.') {
board[x][++y] = i + 'B';
++i;
} break;
case 2: if ((x - 1) >= 0
&& board[x - 1][y] == '.') {
board[--x][y] = i + 'B';
++i;
} break;
case 3: if ((x + 1) < ROW_SIZE
&& board[x + 1][y] == '.') {
board[++x][y] = i + 'B';
++i;
} break;
default: if (board[x][y] == '.')
board[x][y] = i + 'B';
break;
}
// Reset the random directions
dir = rand() % 4;
}
// Print the board
for (x = 0; x < ROW_SIZE; x++) {
for (y = 0; y < ROW_SIZE; y++)
printf("%4c ", board[x][y]);
printf("\n");
}
return 0;
}

Sudoku Solving Function Explanation

I have been searching for a Sudoku Solving Algorithm for a while and I found this code. But I have some difficulties. I can't understand it. If there are conflicts with all numbers between 1 and 9 in a single cell, the program should stop, right? But it continues. Can somebody explain me how the code works, please? Here it is:
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1) //We find the first cell in which we can change the number
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j)) //We are checking for conflicts
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
if(Game.Help_Solve(nextrow, nextcol)) return true;
}
}
board[i][j] = 0;
return false;
}
Not enough code to explain properly, what happens in Game.Check_Conflicts(p, i, j), is this function getting called recursively?
Here is the whole code if you want to see it:
#include <iostream>
#include <iomanip>
#include <time.h>
#include <cstdlib>
#include <windows.h>
using namespace std;
class Sudoku
{
private:
int board[9][9];
int change[9][9];
public:
Sudoku();
void Print_Board();
void Add_First_Cord();
bool Help_Solve(int i, int j);
bool Check_Conflicts(int p, int i, int j);
};
Sudoku Game;
void setcolor(unsigned short color) //The function that you'll use to
{ //set the colour
HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hcon,color);
}
Sudoku::Sudoku()
{
for(int i = 0; i <= 9; i++)
for(int j = 0; j <= 9; j++)
board[i][j] = 0;
}
void Sudoku::Print_Board()
{
for(int i = 1; i <= 9; i++)
{
for(int j = 1; j <= 9; j++)
{
if(change[i][j] == 1)
{
setcolor(12);
cout << board[i][j] << " ";
setcolor(7);
}
else cout << board[i][j] << " ";
if(j%3 == 0) cout << "| ";
}
cout << endl;
if(i%3 == 0) cout << "------+-------+--------" << endl;
}
}
void Sudoku::Add_First_Cord()
{
board[1][1] = 5; change[1][1] = 1;
board[1][2] = 3; change[1][2] = 1;
board[1][5] = 7; change[1][5] = 1;
board[2][1] = 6; change[2][1] = 1;
board[2][4] = 1; change[2][4] = 1;
board[2][5] = 9; change[2][5] = 1;
board[2][6] = 5; change[2][6] = 1;
board[3][2] = 9; change[3][2] = 1;
board[3][3] = 8; change[3][3] = 1;
board[3][8] = 6; change[3][8] = 1;
board[4][1] = 8; change[4][1] = 1;
board[4][5] = 6; change[4][5] = 1;
board[4][9] = 3; change[4][9] = 1;
board[5][1] = 4; change[5][1] = 1;
board[5][4] = 8; change[5][4] = 1;
board[5][6] = 3; change[5][6] = 1;
board[5][9] = 1; change[5][9] = 1;
board[6][1] = 7; change[6][1] = 1;
board[6][5] = 2; change[6][5] = 1;
board[6][9] = 6; change[6][9] = 1;
board[7][2] = 6; change[7][2] = 1;
board[7][7] = 2; change[7][7] = 1;
board[7][8] = 8; change[7][8] = 1;
board[8][4] = 4; change[8][4] = 1;
board[8][5] = 1; change[8][5] = 1;
board[8][6] = 9; change[8][6] = 1;
board[8][9] = 5; change[8][9] = 1;
board[9][5] = 8; change[9][5] = 1;
board[9][8] = 7; change[9][8] = 1;
board[9][9] = 9; change[9][9] = 1;
}
bool Sudoku::Check_Conflicts(int p, int i, int j)
{
for(int k = 1; k <= 9; k++)
if(board[i][k] == p) return false;
for(int q = 1; q <= 9; q++)
if(board[q][j] == p) return false;
/*
*00
000
000
*/
if((j == 1 || j == 4 || j == 7) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j+1] == p || board[i][j+2] == p || board[i+1][j] == p ||
board[i+2][j] == p || board[i+1][j+1] == p || board[i+1][j+2] == p ||
board[i+2][j+1] == p || board[i+2][j+2] == p)return false;
}
/*
000
000
*00
*/
if((j == 1 || j == 4 || j == 7) && (i == 3 || i == 6 || i == 9))
{
if(board[i-1][j] == p || board[i-2][j] == p || board[i][j+1] == p ||
board[i][j+2] == p || board[i-1][j+1] == p || board[i-1][j+2] == p ||
board[i-2][j+1] == p || board[i-2][j+2] == p)return false;
}
/*
000
*00
000
*/
if((j == 1 || j == 4 || j == 7) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j+1] == p || board[i-1][j+2] == p ||
board[i][j+1] == p || board[i][j+2] == p || board[i+1][j] == p ||
board[i+1][j+1] == p || board[i+1][j+2] == p)return false;
}
/*
0*0
000
000
*/
if((j == 2 || j == 5 || j == 8) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j-1] == p || board[i][j+1] == p || board[i+1][j+1] == p ||
board[i+1][j-1] == p || board[i+1][j] == p || board[i+2][j-1] == p ||
board[i+2][j] == p || board[i+2][j+1] == p)return false;
}
/*
000
0*0
000
*/
if((j == 2 || j == 5 || j == 8) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j+1] == p ||
board[i][j+1] == p || board[i][j-1] == p || board[i+1][j+1] == p ||
board[i+1][j] == p || board[i+1][j-1] == p)return false;
}
/*
000
000
0*0
*/
if((j == 2 || j == 5 || j == 8) && (i == 3 || i == 6 || i == 9))
{
if(board[i][j-1] == p || board[i][j+1] == p || board[i-1][j] == p ||
board[i-1][j+1] == p || board[i-1][j-1] == p || board[i-2][j] == p ||
board[i-2][j+1] == p || board[i-2][j-1] == p) return false;
}
/*
00*
000
000
*/
if((j == 3 || j == 6 || j == 9) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p ||
board[i+1][j-1] == p || board[i+1][j-2] == p || board[i+2][j] == p ||
board[i+2][j-1] == p || board[i+2][j-2] == p) return false;
}
/*
000
00*
000
*/
if((j == 3 || j == 6 || j == 9) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j-2] == p ||
board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p ||
board[i+1][j-1] == p || board[i+1][j-2] == p) return false;
}
/*
000
000
00*
*/
if((j == 3 || j == 6 || j == 9) && (i == 3 || i == 6 || i == 9))
{
if(board[i][j-1] == p || board[i][j-2] == p || board[i-1][j] == p ||
board[i-1][j-1] == p || board[i-1][j-2] == p || board[i-2][j] == p ||
board[i-2][j-1] == p || board[i-2][j-2] == p) return false;
}
return true;
}
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1)
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j))
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
if(Game.Help_Solve(nextrow, nextcol)) return true;
}
}
board[i][j] = 0;
return false;
}
int main()
{
Game.Add_First_Cord();
Game.Help_Solve(1, 1);
Game.Print_Board();
system("pause");
return 0;
}
It looks like Sudoku::Check_Conflicts returns true if the number CAN be placed there, or false if it CAN'T be placed there due to a simple conflict. A different function name could maybe better self-document the code.
The thing is rhat I can't understand why it continues if in the end it
returns false :/
It doesn't ALWAYS return at the bottom of the function tho':
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1) //We find the first cell in which we can change the number
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
-------------------------^^^^
returns true if we have filled all squares.
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j)) //We are checking for conflicts
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
-----------------------------------------------------^^^^
returns when we have filled everything!
if(Game.Help_Solve(nextrow, nextcol)) return true;
---------------------------------------------------------^^^^
returns if we filled at the next level of solution.
}
}
board[i][j] = 0;
return false;
-----------^^^^^ returns if we failed to fill the whole thing.
}
As someone else mentioned in a comment, there are some trivial things that can be done to improve on the algorithm - such as looking for the "most suitable place to fill first" [which doesn't improve the worst case, but it does improve the typical case].
I have written a Sudoku solver that uses a similar algorithm, but it tries to find the cell with the lowest number of candidates (possible numbers to go in the that cell) and only tries recursively if there are multiple choices.