Web lists-archives.com

[Mingw-users] Application behaves differently in different versions of MSys




Greetings!

The program maze_game is a simple recreation of a text adventure engine. It displays information about the room that the player is currently in, and then asks the player for an integer to determine their chosen course of action - 0 to quit. In MSys 1, maze_game works as expected. However, in MSys 2, maze_game will wait for the player to enter multiple integers before executing as if the integers had been entered one by one.

I have attached screenshots.

Kind regards,
Kai

// Author:      Kai Renshaw
// Student ID:  101071667
// Program:     MazeGame
// Date:        17/03/16
// Description: A simple text adventure engine

#include "terminal_user_input.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// declare an enum for the directions
typedef enum { NORTH, SOUTH, EAST, WEST } direction;

// forward declare the room pointer. The room_ptr type is a pointer to struct room_data
typedef struct room_data *room_ptr;

// a path goes from one room to another in this game
typedef struct
{
	direction 	heading;		// direction this heads
	my_string	view_text;		// text to show the user when they look at the room
	my_string	travel_text;	// text to show the user when they use this path
	room_ptr	destination;	// the room they end up in when they use this path
} path_data, *path_ptr;

typedef struct room_data
{
	my_string 	title, description;	// the title and description of the room
	path_ptr	exits;				// a pointer to dynamic memory for the exits (array)
	int 		exit_count;			// the number of exits in this room
} room_data;

typedef struct
{
	room_ptr	rooms;				// pointer to dynamic array of rooms (array)
	int 		room_count;			// the number of rooms in the array
} maze_data;

// Convert a character into a direction.
// Used when file is loaded
direction ch_to_dir(char ch)
{
	switch (ch)
	{
	case 'n': case 'N': return NORTH;
	case 's': case 'S': return SOUTH;
	case 'e': case 'E': return EAST;
	case 'w': case 'W': return WEST;
	default: return NORTH;
	}
}

// Converts a direction into a string
// Uses my_string as you cannot return an array of characters
my_string dir_to_string(direction dir)
{
	my_string result;
	
	switch (dir)
	{
	case NORTH:
		strncpy(result.str, "North", 6); // copy includes null
		break;
	case SOUTH:
		strncpy(result.str, "South", 6);
		break;
	case EAST:
		strncpy(result.str, "East", 5);
		break;
	case WEST:
		strncpy(result.str, "West", 5);
		break;
	default:
		strncpy(result.str, "Unknown", 8);
	}
	
	return result;
}

// Adds a path from one room to another.
// - from_room = 	pointer to the room it heads from
// - to_room = 		pointer to the room it heads to
// - head = 		direction of path
// - view_text = 	text to show user when they view the path
// - travel_text = 	text to show user when they use this path
void add_path(room_ptr from_room, room_ptr to_room, direction head, my_string view_text, my_string travel_text)
{
	int last_idx;
	path_ptr new_exits;
	
	// increase number of exits
	++(from_room->exit_count);
	
	new_exits = (path_ptr)realloc(from_room->exits, sizeof(path_data) * from_room->exit_count);
	
	if (new_exits == NULL)
	{
		printf("Error allocating space in add_path -> either out of memory or realloc call not added.");

		exit(EXIT_FAILURE);
	}
	
	from_room->exits = new_exits;
	
	last_idx = from_room->exit_count - 1;
	from_room->exits[last_idx].destination = to_room;
	from_room->exits[last_idx].heading = head;
	from_room->exits[last_idx].view_text = view_text;
	from_room->exits[last_idx].travel_text = travel_text;
}

//
// Loads the maze from file.
//
void load_maze(const char* filename, maze_data* maze)
{
	FILE* input;
	char dir;
	int room_count, exit_count, from_room_idx, to_room_idx;
	int room_data_size;
	int i;
	my_string view_text, travel_text;
	direction head;
	
	input = fopen(filename, "r");
	
	if (input == NULL)
	{
		printf("Unable to open maze file.");

		exit(EXIT_FAILURE);
	}
	
	// Read the number of rooms
	fscanf(input, "%d ", &room_count);
	maze->room_count = room_count;
	
	// Allocate space for rooms in memory
	room_data_size = sizeof(room_data) * room_count;
	maze->rooms = (room_ptr)malloc(room_data_size);
	
	// Clear the space so it is all full of 0s
	memset(maze->rooms, 0, room_data_size);
	
	// Loop for each room and read it from the file
	for (i = 0; i < room_count; ++i)
	{
		// printf("Loading room %d\n", i);
		fscanf(input, "%255[^\n] ", maze->rooms[i].title.str);
		fscanf(input, "%255[^\n] ", maze->rooms[i].description.str);
		maze->rooms[i].exit_count = 0;
		maze->rooms[i].exits = NULL;
	}
	
	fscanf(input, "%d ", &exit_count);
	// printf("%d\n", exit_count);
	
	for (i = 0; i < exit_count; ++i)
	{
		fscanf(input, "%d %d %c ", &from_room_idx, &to_room_idx, &dir);
		fscanf(input, "%255[^\n] ", view_text.str);
		fscanf(input, "%255[^\n] ", travel_text.str);
		
		printf("Adding a door from %d (index %d) to %d (index %d) -> %c\n",
			from_room_idx, 		// values in the file are 1 based...
			from_room_idx - 1, 	// index are 0 based so -1 to get array index
			to_room_idx,
			to_room_idx - 1, 	// same for the to_room_idx
			dir);
		printf(" from room is -> %s\n", maze->rooms[from_room_idx - 1].title.str);
		
		add_path(&(maze->rooms[from_room_idx - 1]), &(maze->rooms[to_room_idx - 1]), ch_to_dir(dir), view_text, travel_text);
	}
	
	fclose(input);
}

//
// shows the room to the user
//
void show_room(room_ptr room)
{
	int i;
	my_string myString;
	
	printf("----- %s -----\n", room->title.str);
	printf("%s\n\n", room->description.str);
	
	printf("There are exits heading...\n");
	
	for (i = 0; i < room->exit_count; ++i)
	{
		myString = dir_to_string(room->exits[i].heading);
		printf("Here\n");
		
		printf("\t%d: [%s] %s\n",
			i + 1,
			myString.str,
			room->exits[i].view_text.str);
	}
	printf("\n");
}

//
// entry point - loops the game until user enter 0
//
int main(int argc, char* argv[])
{
	maze_data my_maze;
	room_ptr player_room;
	int option;
	
	load_maze("maze.txt", &my_maze);
	
	player_room = &my_maze.rooms[0];
	
	do
	{
		// show the player the room
		show_room(player_room);
		
		// get their exit choice
		option = read_integer_range("Take exit (0 quit): ", 0, player_room->exit_count) - 1;
		
		if (option >= 0)
		{
			// print the travel text
			printf("\n%s\n\n", player_room->exits[option].travel_text.str);
			
			player_room = player_room->exits[option].destination;
		}
	} while (option != -1);
}

Attachment: msys1.png
Description: msys1.png

Attachment: msys2-1.png
Description: msys2-1.png

Attachment: msys2-2.png
Description: msys2-2.png

// =============================
// = User Input Functions in C =
// =============================

#include "terminal_user_input.h"
#include <stdio.h>

//
// Reads a string of up to 255 characters + 1 for null
//
my_string read_string(const char* prompt)
{
	my_string result;     // declares a 'my_string' variable (contains the array of characters)
	
	printf("%s", prompt); // output the string from the prompt "%s" defines where to place the string in the output
	scanf(" %255[^\n]%*c", result.str); // scan the input looking for up to 255 characters (that are not newlines), read this into the string variable
	
	return result; // return the my string value
}

//
// Reads a integer from the user.
//
int read_integer(const char* prompt)
{
	my_string line;
	int result;    // where we will store the result of the function
	char temp;  //used to check nothing comes after the int
	
	// Read in the string the user entered.
	line = read_string(prompt);
	
	// scan the string, looking for a number ... followed by nothing
	// sscanf = string scan format
	//          This will "scan" the array of character in line.str (reads this)
	//          " " = skip any spaces
	//          "%d" = read an integer
	//          " " = skip any spaces
	//          "%c" = read a character
	// sscanf returns the number of things it read (0 to 2 in this case)
	//          Loop while this is not equal to 1
	//          0 = did not read a number at the start
	//          1 = read a number, but no character followed it
	//          2 = read a number and a character... like "1 fred" (1 is the number, f is the character)
	while (sscanf(line.str, " %d %c", &result, &temp) != 1)
	{
		// scan found a number followed by something... so its not a whole number
		printf("Please enter a whole number.\n");
		
		// read the next "string" and try again
		line = read_string(prompt);
	}
	
	return result;
}

int read_integer_range(const char* prompt, int min, int max)
{
	int result = read_integer(prompt);
	
	while ((result < min) || (result > max))
	{
		printf("Please enter a number between %d and %d\n", min, max);
		result = read_integer(prompt);
	}
	
	return result;
}

double read_double(const char* prompt)
{
	my_string line;
	double result;    // where we will store the result of the function
	char temp;  // used to check nothing comes after the int
	
	// Read in the string the user entered.
	line = read_string(prompt);

	while (sscanf(line.str, " %lf %c", &result, &temp) != 1)
	{
		// scan found a number followed by something... so it's not a whole number
		printf("Please enter a number.\n");
		
		// read the next "string" and try again
		line = read_string(prompt);
	}
	
	return result;
}
// =============================
// = User Input Functions in C =
// =============================

//
// This header file contains the types and functions/procedures
// in the Terminal User Input code. You can #include "terminal_user_input.h"
// to access these from your project. Remember to compile both your
// program file and the terminal_user_input.c file.
//

//
// The following code makes sure that you can't accidentally
// include this code twice. It is common to see this kind of
// code at the top of a C/C++ header file.
//
#ifndef TERMINAL_USER_INPUT_H
#define TERMINAL_USER_INPUT_H

//
// The my_string type can be used to represent a 'string' in C.
// This needs to be a struct so that it can be returned from
// functions.
//
typedef struct my_string
{
  char str[256]; // my string contains an array of 255 characters + null
} my_string;

//
// Reads a string of up to 255 characters + 1 for null
//
my_string read_string(const char* prompt);

//
// Reads a integer from the user.
//
int read_integer(const char* prompt);

//
// Reads a integer from the user in a given range.
//
int read_integer_range(const char* prompt, int min, int max);

//
// Reads a double from the user.
//
double read_double(const char* prompt);

#endif
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785471&iu=/4140
_______________________________________________
MinGW-users mailing list
MinGW-users@xxxxxxxxxxxxxxxxxxxxx

This list observes the Etiquette found at 
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Also: mailto:mingw-users-request@xxxxxxxxxxxxxxxxxxxxx?subject=unsubscribe