This repository has been archived on 2025-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
csce420pine64backup/hw1/hw1pr3/hw1pr3.cpp

318 lines
5.1 KiB
C++
Raw Permalink Normal View History

2017-10-24 08:49:03 -05:00
// Alexander Huddleston 223000555
// CSCE420
// Due: October 2, 2017 (changed to 4)
// hw1pr3.cpp
// Purpose: A breadth-first search program solving a 15-puzzle problem.
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
// I could move this into a separate header file, due to time
// constrains I am keeping it in main for now.
class GameBoard
{
private:
// A string representing the state of the board.
string state = "";
// Which index the blank tile is at.
int blank = 0;
// List of game moves so far.
vector<string> moves;
public:
// Should only be used at the beginning to set initial state.
void setBoardState(string s)
{
state = s;
blank = s.find('a');
}
// Return the current board state.
string getBoardState()
{
return state;
}
// Return the vector of move strings.
vector<string> getMoves()
{
return moves;
}
// Change board state, make move. Not necessarily in that order.
void swap(char c)
{
char temp = 'p';
switch(c)
{
case 'l':
temp = state[blank - 1];
state[blank - 1] = 'a';
state[blank] = temp;
blank = --blank;
break;
case 'r':
temp = state[blank + 1];
state[blank + 1] = 'a';
state[blank] = temp;
blank = ++blank;
break;
case 'u':
temp = state[blank - 4];
state[blank - 4] = 'a';
state[blank] = temp;
blank = blank - 4;
break;
case 'd':
temp = state[blank + 4];
state[blank + 4] = 'a';
state[blank] = temp;
blank = blank + 4;
break;
default:
break;
}
// Debugging
//print_move(c, state);
moves.push_back(c + state);
}
// Check if a move is legal.
bool isLegal(char c)
{
if(c == 'l')
{
return ((blank % 4) > 0);
}
if(c == 'r')
{
return ((blank % 4) < 3);
}
if(c == 'u')
{
return (blank > 3);
}
if(c == 'd')
{
return (blank < 12);
}
}
// Check if we have solved the puzzle
bool isSolved(string s)
{
if(moves.size() > 0)
{
return !(moves[moves.size() - 1].substr(1).compare(s));
}
else
{
return !(state.compare(s));
}
}
// Useful if we want the previous board state back.
void resetLastMove()
{
if(moves.size() > 0)
{
moves.pop_back();
moves.pop_back();
}
else
{
cerr << "Nothing to reset." << endl;
}
}
} gb;
// Global GameBoard queue.
queue<GameBoard> gbq;
string get_input_game_board()
{
string input = "";
getline(cin, input);
string output = "";
string token = "";
for(char c : input)
{
if(c == ',')
{
output += (char)(stoi(token) + 97);
token = "";
continue;
}
else
{
token += c;
}
}
output += (char)(stoi(token) + 97);
return output;
}
void print_move(char m, string gb)
{
string move = "";
switch(m)
{
case 'l':
move = "Left";
break;
case 'r':
move = "Right";
break;
case 'u':
move = "Up";
break;
case 'd':
move = "Down";
break;
default:
move = "Start";
break;
}
for(int x = 0; x < 16; ++x)
{
if(x == 0)
{
cout << "\t" << move << "\t";
}
else if(x % 4 == 0)
{
cout << "\n\t\t";
}
if(((int)gb[x]) - 97 < 10)
{
cout << ((int)gb[x] - 97) << " ";
}
else
{
cout << ((int)gb[x] - 97) << " ";
}
}
if(m == 's')
{
cout << "\nSwap the blank\n";
}
else
{
cout << "\n\n";
}
}
GameBoard solve_game(GameBoard gb, string solved)
{
gbq.pop();
if(gb.isSolved(solved))
{
return gb;
}
if(gb.isLegal('l'))
{
gb.swap('l');
gbq.push(gb);
if(gb.isSolved(solved))
{
return gb;
}
else
{
gb.swap('r');
gb.resetLastMove();
}
}
if(gb.isLegal('r'))
{
gb.swap('r');
gbq.push(gb);
if(gb.isSolved(solved))
{
return gb;
}
else
{
gb.swap('l');
gb.resetLastMove();
}
}
if(gb.isLegal('u'))
{
gb.swap('u');
gbq.push(gb);
if(gb.isSolved(solved))
{
return gb;
}
else
{
gb.swap('d');
gb.resetLastMove();
}
}
if(gb.isLegal('d'))
{
gb.swap('d');
gbq.push(gb);
if(gb.isSolved(solved))
{
return gb;
}
else
{
gb.swap('u');
gb.resetLastMove();
}
}
return solve_game(gbq.front(), solved);
}
int main()
{
// Initializing with simple test case just in case something goes wrong.
string solved = "bcdefghijklmnopa";
string init = "bcdefghijkalnopm";
// Getting input.
cout << "Enter 15-puzzle starting state by rows (0 for blank):" << endl;
init = get_input_game_board();
cout << "Enter ending state by rows (0 for blank):" << endl;
solved = get_input_game_board();
// Push starting board into queue, start recursion.
gb.setBoardState(init);
gbq.push(gb);
gb = solve_game(gbq.front(), solved);
// Print the solution.
cout << "Solution:" << endl;
print_move('s', init);
if(gb.getMoves().size() > 0)
{
for(string m : gb.getMoves())
{
char c = m[0];
string state = m.substr(1);
print_move(c, state);
}
}
// I added various pieces of code to help the program
// if the user decides to put in an already solved puzzle.
if(gb.getMoves().size() > 0)
{
cout << "Done!\tGenerated " << gb.getMoves().size() << " states." << endl;
}
else
{
cout << "You gave me a solved puzzle." << endl;
}
return 0;
}