我在C中创建了一个连接4游戏,部分游戏正在加载并保存游戏状态..它的保存方式是通过下面的代码块
if (strncmp (temp, "save", 5) == 0){
int r, c;
// this writes the game settings to a file
int *rows = &num_rows;
int *cols = &num_columns;
int *len = &length_to_win;
FILE *fp = fopen("gameSave.txt", "w+");
fprintf(fp, "%d ", *rows);
fprintf(fp, "%d ", *cols);
fprintf(fp, "%d ", *len);
fprintf(fp, "\n\n");
for (r = 0; r < num_rows; r++) {
for (c = 0; c < num_columns; c++) {
fprintf(fp, "%c ", aPtr[r][c]);
}
fprintf(fp, "\n");
}
printf("Game Saved\n");
fclose(fp);
}
&#34;温度&#34;指用户输入,通常是玩家希望放置其作品的列号;但是,如果他们进入&#34;保存,&#34;然后它将执行这段代码并创建一个看起来像这样的文件
cat gameSave.txt
5 5 4
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
9 9 9 9 9
9 9 9 9 9
5 5 4指的是行列和长度要赢,而它下面的2D数组(由两个\ n&s;分隔)是电路板的字符表示(它们确实是字符,而不是整数)。我的问题是,我在下面使用这段代码来加载游戏中的保存数据
if (strncmp (temp, "load", 5) == 0){
int r, c;
// this loads the game settings into game
FILE *fp = fopen("gameSave.txt", "r");
fscanf(fp, "%d %d %d", &num_rows, &num_columns, &length_to_win);
fscanf(fp, "\n\n");
aPtr = malloc(num_rows * sizeof(char*));
for (i = 0; i < num_rows; i++){
aPtr[i] = malloc(num_columns * sizeof (char));
}
for (r = 0; r < num_rows; r++) {
for (c = 0; c < num_columns; c++) {
fscanf(fp, "%c ", aPtr[r][c]);
}
fscanf(fp, "\n");
}
printf("Game Loaded\n");
fclose(fp);
}
这会成功加载游戏设置(行,列和长度以获胜);然而,应该加载实际游戏状态的代码行(下面)
for (r = 0; r < num_rows; r++) {
for (c = 0; c < num_columns; c++) {
fscanf(fp, "%c ", aPtr[r][c]);
}
fscanf(fp, "\n");
}
给我一个警告,特别是行
fscanf(fp, "%c ", aPtr[r][c]);
警告是
&#34;警告:格式指定类型&#39; char *&#39;但是论证的类型是&#39; int&#39; [-Wformat]&#34;
这令人困惑......因为它基本上与保存块中使用的完全相同的代码行
fprintf(fp, "%c ", aPtr[r][c]);
并没有给我任何问题......对于到底发生了什么有什么想法?如果你想自己运行它,只需注释掉那个用于拉入实际游戏状态的加载代码。完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
void initialize(int num_rows, int num_cols, char **aPtr) {
int i, r, c;
for (r = 0; r < num_rows; r++) {
for (c = 0; c < num_cols; c++) {
aPtr[r][c] = '9';
}
}
}
// end of initialize
void printBoard(int num_rows, int num_columns, char **aPtr) {
int row, col;
int r, c;
for (r = 0; r < num_rows; r++) {
for (c = 0; c < num_columns; c++) {
printf("%c ", aPtr[r][c]);
}
printf("\n");
}
printf("\n");
puts("------ Connect *Four ------");
puts("Connect X Command Line Game");
// for fancy top of board frame
printf("&&");
for(col = 1; col < num_columns; col++) {
printf("====");
}
printf("===");
printf("&&\n");
// for the rows/columns of the board
for(row = num_rows - 1; row >= 0; row--){
printf("|");
for(col = 0; col < num_columns; col++){
if(aPtr[row][col] == '0') {
printf("| X ");
}
else if(aPtr[row][col] == '1') {
printf("| O ");
}
else {
printf("| ");
}
}
puts("||");
}
// for fancy bottom of board frame
printf("&&");
for(col = 1; col < num_columns; col++) {
printf("====");
}
printf("===");
printf("&&\n");
printf(" ");
if (col < 100){
for(col = 0; col < num_columns; col++) {
if (col < 10) {
printf(" %d ", col + 1);
}
else {
printf("%d ", col + 1);
}
}
puts("\n");
}
}
// end of printBoard
/*Global var to hold the current winner value*/
char winnerVal = '0';
int checkFullBoard(int num_rows, int num_columns, char **aPtr) {
for (int i = 0; i < num_columns; i++) {
if (aPtr[num_rows - 1][i] == '9') {
return 0;
}
}
return 1;
}
/*
* Checks for the first avalible cell to insert token in given column.
* NOTE: This fuction is designed based on row 0 being the bottom (lowest row of the board)
* This means that tokens are inserted from row 0 upward. Based on your tests, this should not cause
* any problems.
*/
int checkForColHeight(int num_rows, int num_columns, int column, char **aPtr) {
for (int i = 0; i < num_rows; i++) {
if (aPtr[i][column] == '9') {
return i;
}
}
return -1;
}
int place_token(char player, int column, int num_rows, int num_columns, char **aPtr) {
/*Check for invalid Parameters*/
if(column > (num_columns - 1) || column < 0 || (player != '1' && player != '0')
|| num_columns <= 0 || num_rows <= 0) {;
return -1;
}
int firstOpenRow = checkForColHeight(num_rows, num_columns, column, aPtr);
if (firstOpenRow == -1) {
return -1;
}else {
aPtr[firstOpenRow][column] = player;
return 1;
}
}
char checkForSeries(int direction, int num_rows, int num_columns, int length_to_win, int r, int c, char **aPtr) {
switch (direction) {
/*Horizontal*/
case 0:
for (int i = 1; i < length_to_win; i++) {
if (aPtr[r][c] == '9' ) {
return '2';
}else if (aPtr[r][c] != aPtr[r][c + i] ) {
return '2';
}
}
return aPtr[r][c];
break;
/*Vertical*/
case 1:
for (int i = 1; i < length_to_win; i++) {
if (aPtr[r][c] == '9' ) {
return '2';
}else if (aPtr[r][c] != aPtr[r + i][c] ) {
return '2';
}
}
return aPtr[r][c];
break;
/*Left Diag*/
case 2:
for (int i = 1; i < length_to_win; i++) {
if (aPtr[r][c] == '9' ) {
return '2';
}else if (aPtr[r][c] != aPtr[r + i][c - i] ) {
return '2';
}
}
return aPtr[r][c];
break;
/*Right Diag*/
case 3:
for (int i = 1; i < length_to_win; i++) {
if (aPtr[r][c] == '9' ) {
return '2';
}else if (aPtr[r][c] != aPtr[r + i][c + i] ) {
return '2';
}
}
return aPtr[r][c];
break;
return '2';
}
return '0';
}
/*Interate over each row and column. For each cell in the row, check for series of tokens*/
int checkHorizontal(int num_rows, int num_columns, int length_to_win, char **aPtr){
int r, c;
for (r = 0; r < num_rows; r++) {
for(c = 0; c < num_columns - (length_to_win - 1); c++) {
char winner = checkForSeries(0, num_rows, num_columns, length_to_win, r, c, aPtr);
if(winner != '2') {
winnerVal = winner;
return 1;
}
}
}
return 0;
}
/*Interate over each row and column. For each cell in the row, check for series of tokens*/
int checkVertical(int num_rows, int num_columns, int length_to_win, char **aPtr){
int r, c;
for (c = 0; c < num_columns; c++) {
for(r = 0; r < num_rows - (length_to_win - 1); r++) {
char winner = checkForSeries(1, num_rows, num_columns, length_to_win, r, c, aPtr);
if(winner != '2') {
winnerVal = winner;
return 1;
}
}
}
return 0;
}
/*Interate over each row and column. For each cell in the row, check for series of tokens*/
int checkDiagLeft(int num_rows, int num_columns, int length_to_win, char **aPtr){
int r, c;
for (r = 0; r < num_rows - (length_to_win - 1); r++) {
for(c = num_columns - 1; c > (length_to_win - 2); c--) {
char winner = checkForSeries(2, num_rows, num_columns, length_to_win, r, c, aPtr);
if(winner != '2') {
winnerVal = winner;
return 1;
}
}
}
return 0;
}
/*Interate over each row and column. For each cell in the row, check for series of tokens*/
int checkDiagRight(int num_rows, int num_columns, int length_to_win, char **aPtr){
// printf("%s\n", "Check Right Diag: ");
int r, c;
for (r = 0; r < num_rows - (length_to_win - 1); r++) {
// printf("%s", "Row #: ");
// printf("%d\n", r);
for(c = 0; c < num_columns - (length_to_win - 1); c++) {
// printf("%s", "Col #: ");
// printf("%d\n", c);
char winner = checkForSeries(3, num_rows, num_columns, length_to_win, r, c, aPtr);
if(winner != '2') {
winnerVal = winner;
// printf("%s", "Row Location: ");
// printf("%d\n", r);
// printf("%s", "Col Location: ");
// printf("%d\n", c);
return 1;
}
}
}
return 0;
}
/*Return the integer representation of the winning player, -1 if a tie or error*/
char winner(int num_rows, int num_columns, int length_to_win, char **aPtr) {
/*Check for invalid Parameters*/
if (length_to_win <= 0 || length_to_win > num_columns || num_columns <= 0 || num_rows <= 0) {
return '2';
}
if (checkHorizontal(num_rows, num_columns, length_to_win, aPtr)
|| checkVertical(num_rows, num_columns, length_to_win, aPtr)
|| checkDiagLeft(num_rows, num_columns, length_to_win, aPtr)
|| checkDiagRight(num_rows, num_columns, length_to_win, aPtr)
) {
return winnerVal;
}
if(checkFullBoard(num_rows, num_columns, aPtr)) {
return '2';
}
return '2';
}
// *******************************************************************************************************
// *******************************************************************************************************
int main (int argc, char *argv[]) {
setvbuf(stdout, NULL, _IONBF, 0);
int num_rows = 7;
int num_columns = 7;
int length_to_win = 4;
int i;
int index;
char **aPtr;
// FILE *fp = fopen("test.txt", "r");
printf("Starting Game\n");
// this loop checks for command line arguments and sets game variables accordingly.
for(index = 0; index < argc; ++index) {
if ( strncmp( argv[index], "-h", 5) == 0 ) {
num_rows =atoi(argv[index + 1]);
}
if ( strncmp( argv[index], "-height", 5) == 0 ) {
num_rows =atoi(argv[index + 1]);
}
if ( strncmp( argv[index], "-w", 5) == 0 ) {
num_columns = atoi(argv[index + 1]);
}
if ( strncmp( argv[index], "-width", 5) == 0 ) {
num_columns = atoi(argv[index + 1]);
}
if ( strncmp( argv[index], "-s", 5) == 0 ) {
num_rows = atoi(argv[index + 1]);
num_columns = atoi(argv[index + 1]);
}
if ( strncmp( argv[index], "-square", 5) == 0 ) {
num_rows = atoi(argv[index + 1]);
num_columns = atoi(argv[index + 1]);
}
if ( strncmp( argv[index], "-c", 5) == 0 ) {
length_to_win = atoi(argv[index + 1]);
}
if ( strncmp( argv[index], "-connect", 5) == 0 ) {
length_to_win = atoi(argv[index + 1]);
}
}
// these conditionals check for valid board size
if (num_rows <= 0 || num_columns <= 0 ){
printf("%s\n","You entered a width or length that was invalid." );
}
if (length_to_win <= 0 || length_to_win > (num_rows - 1)) {
printf("%s\n","You entered a winning length that was invalid." );
}
// create the space for the board
aPtr = malloc(num_rows * sizeof(char*));
for (i = 0; i < num_rows; i++){
aPtr[i] = malloc(num_columns * sizeof (char));
}
initialize(num_rows, num_columns, aPtr);
int answer;
int attmpt;
char player = '0';
printf("%s\n", "*********************");
printf("%s\n", " Starting Board ");
printf("%s\n", "*********************");
puts("\n");
printBoard(num_rows, num_columns, aPtr);
printf("Player: %cs Turn\n", player + 1);
puts("\n");
/*Start game loop*/
while(1) {
// prompts the user to select which column they want their piece to be placed
// -1 on the temp because the first column is technically 0 so if a player
// wants to place their piece in column "1", it'll be placed at index[0] accordingly
printf("%s\n", "Enter Column # To Place Token");
int column;
char temp[20];
char temp2[20];
scanf("%s", temp);
if (strncmp (temp, "save", 5) == 0){
int r, c;
// this writes the game settings to a file
int *rows = &num_rows;
int *cols = &num_columns;
int *len = &length_to_win;
FILE *fp = fopen("gameSave.txt", "w+");
fprintf(fp, "%d ", *rows);
fprintf(fp, "%d ", *cols);
fprintf(fp, "%d ", *len);
fprintf(fp, "\n\n");
for (r = 0; r < num_rows; r++) {
for (c = 0; c < num_columns; c++) {
fprintf(fp, "%c ", aPtr[r][c]);
}
fprintf(fp, "\n");
}
printf("Game Saved\n");
fclose(fp);
}
if (strncmp (temp, "load", 5) == 0){
int r, c;
// this loads the game settings into game
FILE *fp = fopen("gameSave.txt", "r");
fscanf(fp, "%d %d %d", &num_rows, &num_columns, &length_to_win);
fscanf(fp, "\n\n");
aPtr = malloc(num_rows * sizeof(char*));
for (i = 0; i < num_rows; i++){
aPtr[i] = malloc(num_columns * sizeof (char));
}
for (r = 0; r < num_rows; r++) {
for (c = 0; c < num_columns; c++) {
fscanf(fp, "%c ", aPtr[r][c]);
}
fscanf(fp, "\n");
}
printf("Game Loaded\n");
fclose(fp);
}
column = atoi(temp) - 1;
attmpt = place_token(player, column, num_rows, num_columns, aPtr);
if ((column < 0 || column > (num_columns - 1)) && (strncmp (temp, "save", 5) != 0) && (strncmp (temp, "load", 5) != 0)) {
printf("%s\n","You entered a column that was invalid. Please try again." );
continue;
}
if (attmpt != 1 && (strncmp (temp, "save", 5) != 0) && (strncmp (temp, "load", 5) != 0)) {
printf("%s\n","This row is already full. Please try again." );
continue;
}
printf("%s\n", "************************");
printf("%s\n", " Board Updated ");
printf("%s\n", "************************");
puts("\n");
printBoard(num_rows, num_columns, aPtr);
puts("\n");
if ((strncmp (temp, "save", 5) != 0) && (strncmp (temp, "load", 5) != 0)) {
if (checkFullBoard(num_rows, num_columns, aPtr)) {
printf("%s\n","This game is a tie. Thanks for Playing.\n");
return 0;
}
}
// this if-statement will constantly be run while the game progresses,
// meaning that winner will be called at every turn and
// all of the win conditions will be checked until a winner is found
char isWin = winner(num_rows, num_columns, length_to_win, aPtr);
if(isWin != '2') {
printf("Player: %c is the winner! Thanks for Playing.\n", isWin + 1);
printf("Play again? (enter 'y' to continue)\n");
scanf("%s", temp2);
if (strncmp (temp2, "y", 5) == 0){
initialize(num_rows, num_columns, aPtr);
printBoard(num_rows, num_columns, aPtr);
puts("\n");
}
else {
printf("Game over, goodbye!\n");
return 0;
}
}
// if a winner is not found then this if/else will continue to switch
// between players at the end of each turn
if ((strncmp (temp, "save", 5) != 0) && (strncmp (temp, "load", 5) != 0) && (strncmp (temp2, "y", 5) != 0)) {
if (player == '1') {
player = '0';
}
else {
player = '1';
}
}
memset(temp, 0, sizeof temp);
memset(temp2, 0, sizeof temp2);
printf("Player: %cs Turn\n", player +1);
} // end of while loop
return 0;
}
答案 0 :(得分:1)
fscanf(fp, "%c ", aPtr[r][c]);
应该是:
fscanf(fp, " %c", &aPtr[r][c]);
在 %c
之前放置一个空格,以便在阅读字符之前跳过换行符和任何其他空格。而且你必须给出一个指向要存储的数组元素的指针。