我在做一道家庭作业题目,有些问题需要帮助。如果你不想帮忙解决这个作业问题,我应该提醒一下,我的老师鼓励我们在完全无法解决问题时在这个网站上寻求帮助。另外,我已经独立完成了基本部分的任务,现在正在尝试一个可选的挑战问题。好了,进入正题!
由于我对OOP和C++都比较新,我无法理解“this->”操作符的含义。虽然我们课堂上没有讲过它,但我在其他地方见过它,并且我猜测它的用途。
对于这个任务,我必须创建一个基于控制台的井字棋游戏。只有挑战任务要求我们创建一个AI对手,而我们不会因此获得任何额外的学分,我只是想知道如何实现它。我正在学习如何使用minimax和游戏树等相关内容,但现在我只是想创建一个“随机选择空位”的函数。
我有一个名为TicTacToe的类,它基本上是整个程序。我将把与问题相关的部分贴在下面,但给我带来错误的那个子例程是:
void TicTacToe::makeAutoMove(){
srand(time(NULL));
int row = rand() % 3 + 1;
int col = rand() % 3 + 1;
if(this->isValidMove(row, col)){
this->makeMove(row, col);
}else{
this->makeAutoMove();
}
}
这个函数的唯一目的是在假设棋盘是空的情况下进行棋子移动。棋盘的设置如下:
char board[4][4];
当我打印它时,它看起来像:
1 2 3
1 - - -
2 - - -
3 - - -
问题在于,有时计算机会进行一些操作,导致我遇到了难以追踪的错误,因为这个函数具有随机性。我认为这是段错误,但我无法确定,因为在调试器中无法复制它。
我认为 "this->" 运算符作为指针,如果一个指针为空并且被访问,就可能出现这个问题。这是正确的吗?有没有方法可以解决这个问题?
我知道对于社区的许多成员来说,这可能是一个非常低级的问题,但只要不带嘲讽的话,我会非常感激您的帮助,不管这个问题有多么愚蠢。我正在学习,这意味着有时候我会问一些愚蠢的问题。
如果需要,这里是我的.cpp文件的更多内容:
TicTacToe::TicTacToe()
{
for(int row = 0; row < kNumRows; row++){
for(int col = 0; col < kNumCols; col++){
if(col == 0 && row == 0){
board[row][col] = ' ';
}else if(col == 0){
board[row][col] = static_cast<char>('0' + row);
}else if(row == 0){
board[row][col] = static_cast<char>('0' + col);
}else{
board[row][col] = '-';
}
}
}
currentPlayer = 'X';
}
char TicTacToe::getCurrentPlayer(){
return currentPlayer;
}
char TicTacToe::getWinner(){
//Check for diagonals (Only the middle square can do this)
char middle = board[2][2];
if(board[1][1] == middle && board[3][3] == middle && middle != '-'){
return middle;
}else if(middle == board[3][1] && middle == board[1][3] && middle != '-'){
return middle;
}
//Check for horizontal wins
for(int row = 1; row < kNumRows; row++){
if(board[row][1] == board[row][2] && board[row][2] == board[row][3] && board[row][1] != '-'){
return board[row][1];
}
}
//Check for vertical wins
for(int col = 1; col < kNumCols; col++){
if(board[1][col] == board[2][col] && board[2][col] == board[3][col] && board[1][col] != '-'){
return board[1][col];
}
}
//Otherwise, in the case of a tie game, return a dash.
return '-';
}
void TicTacToe::makeMove(int row, int col){
board[row][col] = currentPlayer;
if(currentPlayer == 'X'){
currentPlayer = 'O';
}else if(currentPlayer == 'O'){
currentPlayer = 'X';
}
}
//TODO: Make sure this works after you make the make-move function
bool TicTacToe::isDone(){
bool fullBoard = true;
//First check to see if the board is full
for(int col = 1; col < kNumCols; col++){
for(int row = 1; row < kNumRows; row++){
if(board[row][col] == '-'){
fullBoard = false;
}
}
}
//If the board is full, the game is done. Otherwise check for consecutives.
if(fullBoard){
return true;
}else{
//Check for diagonals (Only the middle square can do this)
char middle = board[2][2];
if(board[1][1] == middle && board[3][3] == middle && middle != '-'){
return true;
}else if(middle == board[3][1] && middle == board[1][3] && middle != '-'){
return true;
}
//Check for horizontal wins
for(int row = 1; row < kNumRows; row++){
if(board[row][1] == board[row][2] && board[row][2] == board[row][3] && board[row][1] != '-'){
return true;
}
}
//Check for vertical wins
for(int col = 1; col < kNumCols; col++){
if(board[1][col] == board[2][col] && board[2][col] == board[3][col] && board[1][col] != '-'){
return true;
}
}
}
//If all other tests fail, then the game is not done
return false;
}
bool TicTacToe::isValidMove(int row, int col){
if(board[row][col] == '-' && row <= 3 && col <= 3){
return true;
}else{
//cout << "That is an invalid move" << endl;
return false;
}
}
void TicTacToe::print(){
for(int row = 0; row < kNumRows; row++){
for(int col = 0; col < kNumCols; col++){
cout << setw(3) << board[row][col];
}
cout << endl;
}
}
TicTacToe * ttt = NULL;
。 - Gasimboard[row][col] == '-' && row <= 3 && col <= 3
,否则可能会访问越界。 - dypsrand()
会设置一些被rand()
使用的隐藏全局变量,因此您应该只设置一次,并且程序的开头是一个很好的地方。如果您感兴趣,C++11提供了<random>
库(用法示例),在几乎所有方面都比srand()/rand()
更好。 - bames53