Created
July 29, 2018 18:06
-
-
Save gazmull/e05f2df6b889b9d10b4330de103608ca to your computer and use it in GitHub Desktop.
Tower of Hanoi Case Study
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Author: gazmull <vescalaw@gmail.com> | |
Description: [Case Study] Tower of Hanoi with data structuring. | |
*/ | |
#include <iostream> | |
#include <iomanip> | |
using namespace std; | |
int | |
inputSize | |
, moves | |
, * towers | |
, * towerSizes; | |
// Towers-related functions | |
void | |
printTowers() | |
, modifyTowers(int towerA, int towerB); | |
// I/O streaming functions | |
void pausePrint(string message = "\n"); | |
// Tower functions | |
namespace Tower { | |
int index(int x, int y) { return (x * inputSize) + y; }; | |
int size(int tower) { return towerSizes[tower]; }; | |
int top(int tower) { return -1 * (size(tower) - inputSize); }; | |
int topValue(int tower) { return towers[index(tower, top(tower))]; }; | |
}; | |
// Initialiser | |
int main() { | |
cout << "Number of towers: "; | |
cin >> inputSize; | |
if (inputSize < 3) | |
return main(); | |
// Use 1D Array for storing tower numbers, with their respective tower size in another array | |
// Please refer to Tower::index for indexing | |
moves = 0; | |
towers = new int[inputSize * inputSize]; | |
towerSizes = new int[inputSize]; | |
// Print vertically | |
for (int i = 0; i < inputSize; i++) | |
for (int j = 0; j < inputSize; j++) | |
if (!i) { | |
towers[Tower::index(0, j)] = j + 1; | |
towerSizes[i] = inputSize; | |
} | |
else { | |
towers[Tower::index(i, j)] = 0; | |
towerSizes[i] = 0; | |
} | |
printTowers(); | |
return 0; | |
} | |
// Display/Update towers sheet | |
void printTowers() { | |
system("cls"); | |
cout | |
<< "Moves occurred: " << moves | |
<< "\nGame Rules:" | |
<< "\n * Only 1 number per move" | |
<< "\n * You cannot stack larger number with a smaller number" | |
<< "\n * You cannot win with getting all numbers back to tower 1 after scrambling them." | |
<< "\n\n"; | |
for (int i = 1; i <= inputSize; i++) | |
cout << setw(5) << i; | |
cout << "\n\n"; | |
for (int i = 0; i < inputSize; i++) { | |
for (int j = 0; j < inputSize; j++) | |
cout << setw(5) << towers[Tower::index(j, i)]; | |
cout << endl; | |
} | |
int | |
towerA | |
, towerB; | |
// Ask for input with space character as separator | |
cout | |
<< endl | |
<< "[MOVE FROM] [MOVE TO]: "; | |
cin >> towerA >> towerB; | |
modifyTowers(towerA - 1, towerB - 1); | |
} | |
/* | |
Towers checker | |
- Malicious act checks | |
- Transferring of number between towers | |
- Check win condition | |
*/ | |
void modifyTowers(int towerA, int towerB) { | |
// Malicious act checks | |
if (towerA == towerB) { | |
pausePrint("Wrong move. You cannot select the same tower."); | |
return printTowers(); | |
} else if (!Tower::topValue(towerA)) { | |
pausePrint("Wrong move. You cannot move anything from an empty tower."); | |
return printTowers(); | |
} else if (Tower::topValue(towerB) && Tower::topValue(towerA) > Tower::topValue(towerB)) { | |
pausePrint("Wrong move. Please move to an empty tower or a tower with higher top number."); | |
return printTowers(); | |
} | |
/* | |
Transferring of number between towers | |
- For some reason, removing `- 1` and/or adding `-1` at `Tower::top` breaks these re-assignments. | |
I have yet to know why... | |
- Update tower sizes | |
- Track moves | |
*/ | |
towers[Tower::index(towerB, Tower::top(towerB) - 1)] = Tower::topValue(towerA); | |
towers[Tower::index(towerA, Tower::top(towerA))] = 0; | |
towerSizes[towerA]--; | |
towerSizes[towerB]++; | |
moves++; | |
// Check win condition | |
if (Tower::size(towerB) == inputSize && towerB) { | |
cout << "You win. Moves occurred: " << moves; | |
pausePrint(); | |
tryAgain: | |
char answer; | |
cout << "Try again? (y/n): "; | |
cin >> answer; | |
switch (answer) { | |
case 'y': | |
// Free memory && call main function | |
delete[] towers; | |
delete[] towerSizes; | |
system("cls"); | |
main(); | |
break; | |
case 'n': | |
exit(0); | |
break; | |
default: goto tryAgain; | |
} | |
} | |
printTowers(); | |
} | |
void pausePrint(string message) { | |
cout << message << endl; | |
system("pause"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment