c - 我对链表有问题。这是一个双重列表的蛇游戏,它不应该吃东西,它只是每 5 步增长 1 个方块
问题描述
- 我对链表有问题。
- 这是一个双重列表的蛇游戏,它不应该吃东西,它只是每 5 步增长 1 个方块。
- 这是一个双重列表的蛇游戏,它不应该吃东西,它只是每 5 步增长 1 个方块。我在蛇初始函数中得到“取消引用 NULL 点”,读取访问冲突。snakeTailPtr 为 0xCDCDCDCD。在无效打印功能
- 项目清单
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#define ROWS 25
#define COLS 75
// terminal escape codes/ANSI escape codes (or ANSI escape sequences)
// "\x1B" is the escape character that tells your terminal that what comes next is not meant to be printed on the screen,
// but rather a command to the terminal (or most likely terminal emulator).
// Turn escape codes ON.
// Turn escape codes ON.
typedef struct node {
int x;
int y;
struct node* next;
struct node* prev;
}NODE;
typedef struct SNAKE {
NODE* head;
NODE* tail;
}SNAKE;
// Moves the cursor to position (x,y) on screen.
// Parameters:
// x: the row of the position.
// y: the column of the position.
void gotoxy( int x, int y );
// Delays the execution of the program.
// Parameters:
// secs: the length of the delay in seconds.
void sleep( float secs );
//My Functions///
void init( void );
void print( SNAKE* snake );
void initialTheBoard( char board[ROWS][COLS] );//Initial the board limits and print them
void initialSnaKE( SNAKE* snake );//initial the snake in the middle
void snakeSpeed( float* delay, int counter );
void checkInput( SNAKE* snake, char* keystoke, char* lastmove, int * newX, int * newY );//Check if to change the snake direction
void SnakeMovment( SNAKE* snake, int counter, float* delay, int newX, int newY, char board[ROWS][COLS] );//move the snake
bool checkIfGameOver( SNAKE* snake, char matrix[ROWS][COLS], int newX, int newY );//check if the game is over
void GameOverPrint( char board[ROWS][COLS] );//Print game over in the middle of the screen when the player lose
void printBoard( char board[ROWS][COLS] );
int main() {
//variables that will be used in the game
float delay = 1.000;
int newX = 0, newY = 0;
int x = ROWS / 2, y = COLS / 2, count = 0;;
bool gameOver = false;
char keystroke = 'd', lastmove = 'd';
char Boardmatrix[ROWS][COLS];
//intial the snake and put him in the middle
SNAKE* snake = (SNAKE*)malloc( sizeof( SNAKE ) );
initialSnaKE( snake );
initialTheBoard( Boardmatrix );
//The Game
while ( gameOver == false )
{
init();
printBoard( Boardmatrix );
print( snake );
count++;
_kbhit();
keystroke = _getch();
checkInput( snake, &keystroke, &lastmove, &newX, &newY );
gameOver = checkIfGameOver( snake, Boardmatrix, newX, newY );
SnakeMovment( snake, count, &delay, newX, newY, Boardmatrix );
snakeSpeed( &delay, count );
sleep( delay );
}
GameOverPrint( Boardmatrix );
}
void initialSnaKE( SNAKE* snake )//maybe x,y of tail need to be different
{
//Snake start in the middle with the right values
//Need to add malloc
NODE* newNode = (NODE*)malloc( sizeof( NODE ) );
newNode->x = ROWS / 2;
newNode->y = COLS / 2;
snake->head = newNode;
snake->tail = newNode;
snake->head->prev = NULL;
snake->head->next = NULL;
}
void initialTheBoard( char board[ROWS][COLS] )
{
for ( int i = 0; i < ROWS; i++ ) {
for ( int j = 0; j < COLS; j++ ) {
board[i][j] = ' ';
}
}
for ( int i = 0; i < ROWS; i++ ) {
board[i][0] = '#';
board[i][COLS - 1] = '#';
}
for ( int i = 0; i < COLS; i++ ) {
board[0][i] = '#';
board[ROWS - 1][i] = '#';
}
}
void printBoard( char board[ROWS][COLS] ) {
for ( int i = 0; i < ROWS; i++ ) {
for ( int j = 0; j < COLS; j++ ) {
printf( "%c", board[i][j] );
}
printf( "\n" );
}
}
void checkInput( SNAKE * snake, char* keystoke, char* lastmove, int* newX, int* newY )
{
if ( *lastmove != 's' && *keystoke == 'w' ) {
snake->head->x = snake->head->x - 1;
*newX = -1;
*newY = 0;
*lastmove = 'w';
}
else if ( *lastmove != 'w' && *keystoke == 's' ) {
snake->head->x = snake->head->x + 1;
*lastmove = 's';
*newX = 1;
*newY = 0;
}
else if ( *lastmove != 'a' && *keystoke == 'd' ) {
snake->head->y = snake->head->y + 1;
*lastmove = 'd';
*newX = 0;
*newY = 1;
}
else if ( *lastmove != 'd' && *keystoke == 'a' ) {
snake->head->y = snake->head->y - 1;
*lastmove = 'a';
*newX = 0;
*newY = -1;
}
else {
if ( *lastmove == 'a' ) {
snake->head->y = snake->head->y - 1;
*newX = 0;
*newY = -1;
}
if ( *lastmove == 'd' ) {
snake->head->y = snake->head->y + 1;
*newX = 0;
*newY = 1;
}
if ( *lastmove == 'w' ) {
snake->head->x = snake->head->x - 1;
*newX = -1;
*newY = 0;
}
if ( *lastmove == 's' ) {
snake->head->x = snake->head->x + 1;
*newX = 1;
*newY = 0;
}
}
}
void SnakeMovment( SNAKE* snake, int counter, float* delay, int newX, int newY, char board[ROWS][COLS] ) {
/*
if (counter < 5) {
print(snake);
}*/
//else {
NODE* newHead = (NODE*)(malloc( sizeof( NODE ) ));
NODE* oldHead = (NODE*)(malloc( sizeof( NODE ) ));
newHead->x = snake->head->x + newX;
newHead->y = snake->head->y + newY;
oldHead = snake->head;
snake->head = newHead;
snake->head->next = oldHead;
oldHead->prev = snake->head;
board[snake->head->x][snake->head->y] = '@';
/*
if (counter % 5 != 0) {
board[snake->tail->x][snake->tail->y] = ' ';
NODE* oldTail;
oldTail = snake->tail->prev;
snake->tail->prev = oldTail->prev;
free(oldTail);
}
print(snake);
}*/
}
void snakeSpeed( float *delay, int counter )
{
if ( *delay > 100 && counter % 5 == 0 )
{
*delay -= (float)0.300;
}
}
// Turn escape codes ON.
void init( void ) {
system( "cls" );
}
bool checkIfGameOver( SNAKE* snake, char matrix[ROWS][COLS], int newX, int newY )
{
int theX = snake->head->x, theY = snake->head->y;
if ( matrix[theX + newX][theY + newY] != ' ' ) {
return true;
}
else {
return false;
}
}
void print( SNAKE* snake ) {
NODE* snakeTailPtr = snake->tail;
while ( snakeTailPtr != NULL ) {
gotoxy( snakeTailPtr->x, snakeTailPtr->y );
snakeTailPtr = snakeTailPtr->prev;
printf( "@" );
}
}
void GameOverPrint( char board[ROWS][COLS] )//need to add board clean
{
initialTheBoard( board );
char gameOverMessage[10] = "Game Over";
int j = 0;
int middleCol = (COLS / 2);
for ( int i = middleCol - 4; i <= middleCol + 4; i++ ) {
board[ROWS / 2][i] = gameOverMessage[j];
j++;
}
printBoard( board );
for ( int i = 0; i < ROWS; i++ ) {
printf( "\n" );
}
}
// Moves the cursor to position (x,y) on screen.
// Parameters:
// x: the row of the position.
// y: the column of the posiiton.
void gotoxy( int x, int y ) {
printf( "\x1b[%d;%df", x, y );
}
void sleep( float secs ) {
clock_t clocks_start = clock();
while ( clock() - clocks_start < secs * CLOCKS_PER_SEC );
}
解决方案
在您的程序上使用调试器时,我发现问题出在函数中SnakeMovement
。
在该函数中,您初始化 struct member variablesx
和of y
,但不初始化 struct member variable 。这就是为什么稍后在函数中访问它时它具有未初始化值 0xCDCDCDCD 的原因,这在取消引用时会导致访问冲突。您可能希望在函数中使用值 NULL 初始化此变量,以便函数中的循环可以检测到已到达列表的末尾。next
newHead
prev
print
SnakeMovement
print
此外,您的函数的以下几行会SnakeMovement
造成内存泄漏:
NODE* oldHead = (NODE*)(malloc( sizeof( NODE ) ));
[...]
oldHead = snake->head;
首先,将动态分配的内存的地址分配给oldHead
,然后用其他值覆盖该变量,这样分配的内存将永远不会被释放(甚至使用)。如果你从不需要内存,那么你不应该分配它。
推荐阅读
- pandas - 按列名查找
- laravel - 如何获取模型的字符串名称?
- c# - 指定的强制转换无效(C#、SQL)
- java - JBoss中的主从服务器是否共享连接池?
- java - 带有数字的 Protobuf 字段名称以意想不到的方式大写
- swift - 尾随闭包语法如何与 PublicSubject 一起使用
。订阅? - responsive-design - 在颤动中将图像的中心与另一个图像的底部对齐
- .net - MSBuild 不包含二进制文件中的嵌入式资源 (nhibernate hbm.xml)
- ldap - Lighthtpd ldap 组成员被忽略
- c++ - 是否可以使用其指针和 void 对象指针调用成员函数?