-
Notifications
You must be signed in to change notification settings - Fork 0
/
utilities.cpp
148 lines (129 loc) · 4.32 KB
/
utilities.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <iostream>
#include "Arena.h"
///////////////////////////////////////////////////////////////////////////
// Auxiliary function implementation
///////////////////////////////////////////////////////////////////////////
// Return a uniformly distributed random int from lowest to highest, inclusive
int randInt(int lowest, int highest)
{
if (highest < lowest)
std::swap(highest, lowest);
return lowest + (rand() % (highest - lowest + 1));
}
bool charToDir(char ch, int& dir)
{
switch (tolower(ch))
{
default: return false;
case 'n': dir = NORTH; break;
case 'e': dir = EAST; break;
case 's': dir = SOUTH; break;
case 'w': dir = WEST; break;
}
return true;
}
// Return false without changing anything if moving one step from (r,c)
// in the indicated direction would hit a wall or run off the edge of the
// arena. Otherwise, update r and c to the position resulting from the
// move and return true.
bool attemptMove(const Arena& a, int dir, int& r, int& c)
{
int rnew = r;
int cnew = c;
switch (dir)
{
case NORTH: if (r <= 1) return false; else rnew--; break;
case EAST: if (c >= a.cols()) return false; else cnew++; break;
case SOUTH: if (r >= a.rows()) return false; else rnew++; break;
case WEST: if (c <= 1) return false; else cnew--; break;
}
if (a.getCellStatus(rnew,cnew) == WALL)
return false;
r = rnew;
c = cnew;
return true;
}
// Recommend a move for a player at (r,c): A false return means the
// recommendation is that the player should stand; otherwise, bestDir is
// set to the recommended direction to move.
bool recommendMove(const Arena& a, int r, int c, int& bestDir)
{
// How dangerous is it to stand?
int standDanger = computeDanger(a, r, c);
// if it's not safe, see if moving is safer
if (standDanger > 0)
{
int bestMoveDanger = standDanger;
int bestMoveDir = NORTH; // arbitrary initialization
// check the four directions to see if any move is
// better than standing, and if so, record the best
for (int dir = 0; dir < NUMDIRS; dir++)
{
int rnew = r;
int cnew = c;
if (attemptMove(a, dir, rnew, cnew))
{
int danger = computeDanger(a, rnew, cnew);
if (danger < bestMoveDanger)
{
bestMoveDanger = danger;
bestMoveDir = dir;
}
}
}
// if moving is better than standing, recommend move
if (bestMoveDanger < standDanger)
{
bestDir = bestMoveDir;
return true;
}
}
return false; // recommend standing
}
int computeDanger(const Arena& a, int r, int c)
{
// Our measure of danger will be the number of robots that might move
// to position r,c. If a robot is at that position, it is fatal,
// so a large value is returned.
if (a.numberOfRobotsAt(r,c) > 0)
return MAXROBOTS+1;
int danger = 0;
if (r > 1)
danger += a.numberOfRobotsAt(r-1,c);
if (r < a.rows())
danger += a.numberOfRobotsAt(r+1,c);
if (c > 1)
danger += a.numberOfRobotsAt(r,c-1);
if (c < a.cols())
danger += a.numberOfRobotsAt(r,c+1);
return danger;
}
#ifdef _MSC_VER // Microsoft Visual C++
#include <windows.h>
void clearScreen()
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hConsole, &csbi);
DWORD dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
COORD upperLeft = { 0, 0 };
DWORD dwCharsWritten;
FillConsoleOutputCharacter(hConsole, TCHAR(' '), dwConSize, upperLeft,
&dwCharsWritten);
SetConsoleCursorPosition(hConsole, upperLeft);
}
#else // not Microsoft Visual C++, so assume UNIX interface
#include <cstring>
void clearScreen()
{
static const char* term = getenv("TERM");
static const char* ESC_SEQ = "\x1B["; // ANSI Terminal esc seq: ESC [
if (term == NULL || strcmp(term, "dumb") == 0)
std::cout << std::endl;
else
std::cout << ESC_SEQ << "2J" << ESC_SEQ << "H" << std::flush;
}
#endif