Поскольку пример не был завершен, я предположил, что table
и last
были глобальными и что DIM был константой.
При вызове tmpSave
в начале сохраняется копия пустой доски.
Inструктура, имеющая table
типа char (*table)[DIM]
, позволяет выделить и освободить память одним вызовом для каждого.Это также упрощает копирование содержимого в table
и из сохраненной копии.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define DIM 4
struct state {
char (*table)[DIM];
struct state *prev;
};
struct state *last = NULL;
char table[DIM][DIM];
void tmpSave ( )
{
struct state *newstate = NULL;
newstate = malloc ( sizeof ( *newstate));//allocate structure
newstate->table = malloc ( sizeof table);//allocate table
memmove (newstate->table, table, sizeof table);//copy table
if ( last != NULL)
{
newstate->prev = last;
last = newstate;
}
else
{
printf ( "\nHi!!\n");
last = newstate;
last->prev = NULL;
}
}
void undo ( void)
{
struct state *prev = last->prev;
if ( last->prev == NULL)
{
printf ( "\nCan't further undo\n");
}
else
{
free ( last->table);//free table
free ( last);//free structure
last = prev;
memmove ( table, last->table, sizeof table);//copy saved table back to table
}
}
void showboard ( void)
{
int i = 0;
for ( i = 0; i < DIM; ++i)
{
printf ( "%.*s\n", DIM, table[i]);//no zero terminator so print only DIM number of characters
}
}
struct state *freestate ( struct state *all)
{
//make sure all structures are free
while ( all) {
struct state *tmp = all;
free ( all->table);//free table
free ( all);//free structure
all = tmp->prev;
}
return NULL;
}
int main( void) {
srand ( time ( NULL));//seed random number generator
memset ( table, '0', sizeof table);//set table to all 0
showboard ( );
tmpSave ( last);//make sure empty table is saved
for ( int each = 0; each < DIM; ++each) {//DIM moves
int row = rand ( ) % DIM;
int col = rand ( ) % DIM;
table[col][row] = each + '1';
tmpSave ( last);//save table
printf ( "\tMove %d\n", each + 1);
showboard ( );
}
for ( int each = 0; each < DIM + 1; ++each) {//undo DIM + 1
printf ( "\tundo %d\n", each + 1);
undo ( );
showboard ( );
}
last = freestate ( last);
return 0;
}
Чтобы ввести dim
во время выполнения, используйте char **table
и выделите при необходимости.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct State state;
struct State {
char **table;
state *prev;
};
state *tmpSave ( state *last, int dim, char **table) {
state *newstate = NULL;
if ( NULL == ( newstate = malloc ( sizeof ( *newstate)))) {//allocate structure
fprintf ( stderr, "malloc newstate problem\n");
return last;
}
if ( NULL == ( newstate->table = malloc ( sizeof *newstate->table * dim))) {//allocate table pointers
fprintf ( stderr, "malloc newstate->table problem\n");
free ( newstate);
return last;
}
for ( int each = 0; each < dim; ++each) {
if ( NULL == ( newstate->table[each] = malloc ( sizeof **newstate->table * dim))) {//chars to pointers
fprintf ( stderr, "malloc newstate->table[each] problem\n");
while ( each--) {
free ( newstate->table[each]);
}
free ( newstate->table);
free ( newstate);
return last;
}
memmove ( newstate->table[each], table[each], dim);//copy table
}
if ( last != NULL) {
newstate->prev = last;
last = newstate;
}
else {
printf ( "\nHi!!\n");
last = newstate;
last->prev = NULL;
}
return last;
}
state *undo ( state *last, int dim, char **table) {
state *prev = last->prev;
if ( last->prev == NULL) {
printf ( "Can't further undo\n");
}
else {
for ( int each = 0; each < dim; ++each) {
free ( last->table[each]);//free chars
}
free ( last->table);//free table pointers
free ( last);//free structure
last = prev;
for ( int each = 0; each < dim; ++each) {
memmove ( table[each], last->table[each], dim);//copy saved table back to table
}
}
return last;
}
void showboard ( int dim, char **table) {
int show = 0;
for ( show = 0; show < dim; ++show) {
printf ( "%.*s\n", dim, table[show]);//no zero terminator so print only dim number of characters
}
}
state *freeall ( state *all, int dim) {
//make sure all structures are free
while ( all) {
state *tmp = all;
for ( int each = 0; each < dim; ++each) {
free ( all->table[each]);//free chars
}
free ( all->table);//free pointers
free ( all);//free structure
all = tmp->prev;
}
return NULL;
}
int main( void) {
char input[100] = "";
int dim = 0;
int scanned = 0;
char extra = 0;
char **table = NULL;
state *last = NULL;
srand ( time ( NULL));//seed random number generator
do {
if ( 1 != scanned) {
printf ( "enter a number only. try again\n");
}
printf ( "enter a number\n");
if ( fgets ( input, sizeof input, stdin)) {
scanned = sscanf ( input, "%d %c", &dim, &extra);
}
else {
fprintf ( stderr, "fgets problem\n");
return 0;
}
} while ( 1 != scanned);
if ( NULL == ( table = malloc ( sizeof *table * dim))) {//allocate pointers
fprintf ( stderr, "problem malloc table\n");
return 0;
}
for ( int each = 0; each < dim; ++each) {
if ( NULL == ( table[each] = malloc ( sizeof **table * dim))) {//allocate chars to pointers
fprintf ( stderr, "problem malloc table[each]\n");
while ( each--) {
free ( table[each]);
}
free ( table);
return 0;
}
memset ( table[each], '-', dim);//set chars to all -
}
showboard ( dim, table);
last = tmpSave ( last, dim, table);//make sure empty table is saved
for ( int move = 0; move < dim; ++move) {//dim number of random moves
int row = rand ( ) % dim;
int col = rand ( ) % dim;
table[col][row] = move + 'A';
last = tmpSave ( last, dim, table);//save table
printf ( "\tMove %d of %d\n", move + 1, dim);
showboard ( dim, table);
printf ( "press enter\n");
if ( ! fgets ( input, sizeof input, stdin)) {
fprintf ( stderr, "fgets problem\n");
last = freeall ( last, dim);
return 0;
}
}
for ( int move = 0; move < dim + 1; ++move) {//try to undo dim + 1 moves
printf ( "\tundo %d of %d\n", move + 1, dim + 1);
last = undo ( last, dim, table);
showboard ( dim, table);
printf ( "press enter\n");
if ( ! fgets ( input, sizeof input, stdin)) {
fprintf ( stderr, "fgets problem\n");
last = freeall ( last, dim);
return 0;
}
}
last = freeall ( last, dim);
return 0;
}