gpt4 book ai didi

c++ - 在 C++ 中使用节点撤消 Board 上的移动!

转载 作者:行者123 更新时间:2023-11-28 02:49:58 24 4
gpt4 key购买 nike

对于这个项目,我的老师给了我代码,它是 1024/2048 游戏的文本版本。游戏开始时,用户从棋盘上的两个数字开始(2 或 4)。然后每次移动都会弹出一个新数字,如果两个相邻数字具有相同的值,它们将加在一起形成这些数字的总和。我必须创建一个节点,这样我才能撤消所做的每一步。我已经成功地能够将每个 Action 传递到节点中。但是当我调用我的 goBack 函数来撤消移动时,它只显示相同的板。这是代码,任何人都可以发现我做错了什么吗?

#include <iostream>
#include <iomanip> // used for setting output field size using setw
#include <cstdlib>
using namespace std;


typedef struct Node {

int *board;// keep track of board
int *score; // keep track of score
int *boardSize; // keep track of the board size
struct Node* pNext; // node pointer
}Node;

Node* goBack(Node* pHead) {
if (pHead != NULL) {
// create a temp pointer to hold the original head
Node* temp = pHead;
// pHead is pointing to next one
pHead = pHead->pNext;
// free the orinal head's memory!!
delete temp;

}

return pHead;
}

Node* addNode(Node* pHead, int board[], int boardSize, int score ) {
// create a new node, and set the letter and count
Node* newNodePtr = new Node();

newNodePtr->board = board;
newNodePtr->boardSize = &boardSize;
newNodePtr->score = &score;


// insert it at the beginning (new node's next is set to original head)
newNodePtr->pNext = pHead;
cout<<"here";
// return the new node's point (which will be the new head)
return newNodePtr;
}


//--------------------------------------------------------------------
// Display ID info
void displayIDInfo()
{
cout << "Dale Reed \n";
cout << "UIC CS 141, Spring 2014 \n";
cout << "Welcome to 1024 and More. \n";
cout << "This program is based off of Gabriele Cirulli's game online at \n";
cout << " bit.ly/great2048 \n";
cout << " \n";
}//end displayIDInfo()


//--------------------------------------------------------------------
// Display Instructions
void displayInstructions()
{
cout << "For each move enter a direction as a letter key, as follows: \n"
<< " W \n"
<< " A S D \n"
<< "where A=left,W=up, D=right and S=down. \n"
<< " \n"
<< "After a move, when two identical valued tiles come together they \n"
<< "join to become a new single tile with the value of the sum of the \n"
<< "two originals. This value gets added to the score. On each move \n"
<< "one new randomly chosen value of 2 or 4 is placed in a random open \n"
<< "square. User input of x exits the game. \n"
<< " \n";
}//end displayInstructions()


//--------------------------------------------------------------------
// Place a randomly selected 2 or 4 into a random open square on
// the board.
void placeRandomPiece( int board[], int boardSize)
{
// Randomly choose a piece to be placed (2 or 4)
int pieceToPlace = 2;
if( rand()%2 == 1) {
pieceToPlace = 4;
}

// Find an unoccupied square that currently has a 0
int index;
do {
index = rand() % (boardSize*boardSize);
}while( board[ index] != 0);

// board at position index is blank, so place piece there
board[ index] = pieceToPlace;
}//end placeRandomPiece()


//--------------------------------------------------------------------
// Prompt for and get board size, dynamically allocate space for the
// board, initialize the board and set the max tile value that
// corresponds to the board size.
void getSizeAndSetBoard( int * &board, // board that is dynamically allocated
int * &previousBoard, // space for copy of board
int &boardSize, // size of the board, entered by user
int &maxTileValue) // max tile value, depending on board size
{
// Prompt for board size and set corresponding game end value
// cout << "Enter the size board you want, between 4 and 12: ";
// cin >> boardSize;

// Allocate space for the 2-d board (and board copy), stored as a 1-d array
board = new int[ boardSize * boardSize]; // e.g. a board of size 4 will have 4x4=16 elements
previousBoard = new int[ boardSize * boardSize];

// Initialize board to all 0's
for( int row=0; row<boardSize; row++) {
for( int col=0; col<boardSize; col++ ) {
board[ row*boardSize + col] = 0;
}
}

// Calculate and display game ending value
for( int i=4; i<boardSize; i++) {
maxTileValue = maxTileValue * 2; // double for each additional board dimension > 4
}
cout << "Game ends when you reach " << maxTileValue << "." << endl;

// Set two random pieces to start game
placeRandomPiece( board, boardSize);
placeRandomPiece( board, boardSize);

}//end getSizeAndSetBoard()


//--------------------------------------------------------------------
// Display the Board
void displayBoard( int *board, int boardSize, int score)
{
// Set display width value depending on boardSize (and corresponding max value)
int displayWidth;
switch( boardSize) {
case 4:
case 5:
case 6:
case 7: displayWidth = 5; break; // up to 8,192
case 8:
case 9:
case 10: displayWidth = 6; break; // up to 65,536
case 11:
case 12: displayWidth = 7; break; // up to 262,144
default:
// Sanity check, should never get here
cout << "Invalid boardSize of " << boardSize
<< ". Exiting program..\n" << endl;
exit( -1);
break;
}

cout << "\n"
<<"Score: " << score << endl;
for( int row=0; row<boardSize; row++) {
cout << " ";
for( int col=0; col<boardSize; col++ ) {
int current = row*boardSize + col; // 1-d index corresponding to row & col
cout << setw( 6); // set output field size to 6 (Requires #include <iomanip> )
// display '.' if board value is 0
if( board[ current] == 0) {
cout << '.';
}
else {
cout << board[ current];
}
}
cout << "\n\n";
}
}//end displayBoard()


//--------------------------------------------------------------------
// Make a copy of the board. This is used after an attempted move
// to see if the board actually changed.
void copyBoard(
int previousBoard[], // destination for board copy
int board[], // board from which copy will be made
int boardSize) // size of the board
{
for( int row=0; row<boardSize; row++) {
for( int col=0; col<boardSize; col++ ) {
int current = row*boardSize + col; // 1-d index corresponding to row & col
previousBoard[ current] = board[ current];
}
}
}//end copyBoard()


//--------------------------------------------------------------------
// See if board changed this turn. If not, no additional piece
// is randomly added and move number does not increment in main().
// Returns true if boards are different, false otherwise.
bool boardChangedThisTurn( int previousBoard[], int board[], int boardSize)
{
// Compare element by element. If one is found that is different
// then return true, as board was changed.
for( int row=0; row<boardSize; row++) {
for( int col=0; col<boardSize; col++ ) {
int current = row*boardSize + col; // 1-d index corresponding to row & col
if( previousBoard[ current] != board[ current]) {
return true;
}
}
}

return false; // No board difference was found
}


// While the 4 functions below (slideLeft(), slideRight(), slideUp(), slideDown() ) could
// be all combined into a single function, that single function would be difficult to
// understand, so these 4 functions were left separate.


//--------------------------------------------------------------------
// Slide all tiles left, combining matching values, updating the score
void slideLeft( int board[], int boardSize, int &score)
{

// handle each row separately
for( int row=0; row<boardSize; row++) {
// set index limit for this row to be index of left-most tile on this row
int limit = row * boardSize;

// Start from the second column and process each element from left to right
for( int col=1; col<boardSize; col++) {

// get 1-d array index based on row and col
int current = row * boardSize + col;

// slide current piece over as far left as possible
while( board[ current-1] == 0 && current > limit) {
board[ current-1] = board[ current];
board[ current] = 0;
current--;
}

// Combine it with left neighbor if values are the same and non zero.
// The additional check for (current > limit) ensures a tile can be combined
// at most once on a move, since limit is moved right every time a combination is made.
// This ensures a row of: 2 2 4 4 ends up correctly as: 4 8 0 0 and not: 8 4 0 0
if( (board[ current-1] == board[ current]) && (board[ current] != 0) && (current > limit)) {
board[ current-1] = board[ current-1] + board[ current];
board[ current] = 0;
limit = current; // Reset row index limit, to prevent combining a piece more than once
score += board[ current-1]; // Update score

}

}//end for( int col...
}//end for( int row...


}//end slideLeft()


//--------------------------------------------------------------------
// Slide all tiles right, combining matching values, updating the score
void slideRight( int board[], int boardSize, int &score)
{

// handle each row separately
for( int row=0; row<boardSize; row++) {
// set index limit for this row to be index of right-most tile on this row
int limit = row * boardSize + boardSize - 1;

// Start from the second-to-last column and process each element from right to left
for( int col=boardSize - 1; col>=0; col--) {

// get 1-d array index based on row and col
int current = row * boardSize + col;

// slide current piece over as far right as possible
while( board[ current+1] == 0 && current < limit) {
board[ current+1] = board[ current];
board[ current] = 0;
current++;
}

// Combine it with right neighbor if values are the same and non zero.
// The additional check for (current < limit) ensures a tile can be combined
// at most once on a move, since limit is moved left every time a combination is made.
// This ensures a row of: 4 4 2 2 ends up correctly as: 0 0 8 4 and not: 0 0 4 8
if( (board[ current+1] == board[ current]) && (board[ current] != 0) && (current < limit)) {
board[ current+1] = board[ current+1] + board[ current];
board[ current] = 0;
limit = current; // Reset row index limit, to prevent combining a piece more than once
score += board[ current+1]; // Update score

}

}//end for( int col...
}//end for( int row...


}//end slideRight()


//--------------------------------------------------------------------
// Slide all tiles up, combining matching values, updating the score
void slideUp( int board[], int boardSize, int &score)
{

// handle each column separately
for( int col=0; col<boardSize; col++) {
// set index limit for this column to be index of top-most tile on this row
int limit = col;

// Start from the second row and process each element from top to bottom
for( int row=1; row<boardSize; row++) {

// get 1-d array index based on row and col
int current = row * boardSize + col;

// slide current piece up as far as possible
while( board[ current-boardSize] == 0 && current > limit) {
board[ current-boardSize] = board[ current];
board[ current] = 0;
current = current - boardSize;
}

// Combine it with upper neighbor if values are the same and non zero.
// The additional check for (current > limit) ensures a tile can be combined
// at most once on a move, since limit is moved down every time a combination is made.
if( (board[ current-boardSize] == board[ current]) && (board[ current] != 0) && (current > limit)) {
board[ current-boardSize] = board[ current-boardSize] + board[ current];
board[ current] = 0;
limit = current; // Reset row index limit, to prevent combining a piece more than once
score += board[ current-boardSize]; // Update score

}

}//end for( int col...
}//end for( int row...


}//end slideUp()


//--------------------------------------------------------------------
// Slide all tiles down, combining matching values, updating the score
void slideDown( int board[], int boardSize, int &score)
{

// handle each column separately
for( int col=0; col<boardSize; col++) {
// set index limit for this column to be index of bottom-most tile on this row
int limit = (boardSize - 1) * boardSize + col;

// Start from the next to last row and process each element from bottom to top
for( int row=boardSize-1; row>=0; row--) {

// get 1-d array index based on row and col
int current = row * boardSize + col;

// slide current piece down as far as possible
while( board[ current+boardSize] == 0 && current < limit) {
board[ current+boardSize] = board[ current];
board[ current] = 0;
current = current + boardSize;
}

// Combine it with lower neighbor if values are the same and non zero.
// The additional check for (current < limit) ensures a tile can be combined
// at most once on a move, since limit is moved up every time a combination is made.
if( (board[ current+boardSize] == board[ current]) && (board[ current] != 0) && (current < limit)) {
board[ current+boardSize] = board[ current+boardSize] + board[ current];
board[ current] = 0;
limit = current; // Reset row index limit, to prevent combining a piece more than once
score += board[ current+boardSize]; // Update score

}

}//end for( int col...
}//end for( int row...


}//end slideDown()


//--------------------------------------------------------------------
// Return true if we're not done, false if we *are* done
// Game is done if board is full and no more valid moves can be made
// or if a tile with maxTileValue has been created.
bool notDone( int board[], // current board
int boardSize, // size of one side of board
int maxTileValue) // max tile value for this size board
{

// See if the maxTileValue is found anywhere on the board.
// If so, game is over.
for( int i=0; i<boardSize*boardSize; i++) {
if( board[ i] == maxTileValue) {
cout << "Congratulations! You made it to " << maxTileValue << " !!!" << endl;
return false; // there are open squares, so we are not done yet
}
}

// See if there are any open squares. If so return true since we aren't done
for( int i=0; i<boardSize*boardSize; i++) {
if( board[ i] == 0) {
return true; // there are open squares, so we are not done yet
}
}

// All squares are full.
// To check if board is done, make a copy of board, then slide left
// and slide down. If resulting board is same as original, we are done
// with game since there are no moves to be made.
int *boardCopy = new int[ boardSize * boardSize];
copyBoard( boardCopy, board, boardSize);
int tempScore = 0; // used as a placeHolder only for function calls below
slideLeft( boardCopy, boardSize, tempScore);
slideDown( boardCopy, boardSize, tempScore);

// Compare each square of boards. If any is different, a move is possible
for( int i=0; i<boardSize*boardSize; i++) {
if( boardCopy[ i] != board[ i]) {
return true; // Game is not done
}
}

cout << "\n"
<< "No more available moves. Game is over.\n"
<< "\n";
return false; // Game is done since all squares are full and there are no moves
}//end notDone()


//--------------------------------------------------------------------

int main()
{
Node *pHead = NULL;
int score = 0;
int boardSize = 4; // user will enter this value. Set default to 4
int *board; // space will be dynamically allocated depending on user selected size
int *previousBoard; // store copy of board, used to see if a move changed the board
int maxTileValue = 1024; // 1024 for 4x4 board, 2048 for 5x5, 4096 for 6x6, etc.
char userInput = ' '; // handles user input
int move = 1; // user move counter

// Display ID info and instructions
displayIDInfo();
displayInstructions();

// get the board size, create and initialize the board, and set the max tile value
getSizeAndSetBoard( board, previousBoard, boardSize, maxTileValue);

// Main loop to display board, prompt for and handle move and check for win
do {
// Display the board
displayBoard( board, boardSize, score);

// Copy board. After attempting a move this is used to verify that the board
// changed, which allows randomly placing an additional piece on board and
// updating the move number.
copyBoard( previousBoard, board, boardSize); // copy from board into previousBoard

// Prompt for and handle user input
cout << move << ". Your move: ";
cin >> userInput;
switch (userInput) {
case 'x':
cout << "Thanks for playing. Exiting program...";
exit( 0);
break;
case 'r':
cout << "\n"
<< "Resetting board \n"
<< "\n";
getSizeAndSetBoard( board, previousBoard, boardSize, maxTileValue);
score = 0;
move = 1;
continue; // go back up to main loop and restart game
break;
case 'a':
slideLeft( board, boardSize, score); // Slide left
pHead = addNode(pHead, board, boardSize, score);
break;
case 's':
slideDown( board, boardSize, score); // Slide down
pHead = addNode(pHead, board, boardSize, score);
break;
case 'd':
slideRight( board, boardSize, score); // Slide right
pHead = addNode(pHead, board, boardSize, score);
break;
case 'w':
slideUp( board, boardSize, score); // Slide up
pHead = addNode(pHead, board, boardSize, score);
break;
case'u':
pHead = goBack(pHead);// go back
break;
case 'p':
// Place a piece on the board
int index; // 1-d array index location to place piece
int value; // value to be placed
cin >> index >> value;
board[ index] = value;
continue; // Do not increment move number or place random piece
break;
default:
cout << "Invalid input, please retry.";
continue;
break;
}//end switch( userInput)

// If the move resulted in pieces changing position, then it was a valid move
// so place a new random piece (2 or 4) in a random open square and update move number.
if( boardChangedThisTurn( previousBoard, board, boardSize)) {
// Place a random piece on board
placeRandomPiece( board, boardSize);

// Update move number after a valid move
move++;
}

// clear the screen, which is system("clear") on UNIX and system("cls") on Windows
//system("clear");
system("cls");

}while( notDone( board, boardSize, maxTileValue));

// Display final board
displayBoard( board, boardSize, score);

cout << "Exiting program...\n\n";
return 0;
}//end main()

最佳答案

newNodePtr->board = board;

您不要在此处复制棋盘。相反,您将指针复制到板。所以你所有的“节点”都存储指向同一个棋盘的指针(这是游戏的当前状态)。

您需要通过分配和复制整个数组来复制板的内容。

关于c++ - 在 C++ 中使用节点撤消 Board 上的移动!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23303040/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com