0% found this document useful (0 votes)
812 views16 pages

The A-Mazing Race

The document describes a program that generates and navigates a randomly generated maze using gyroscope input from a DualShock controller, with the difficulty of the maze increasing based on a command line argument; it includes functions to generate and draw the maze, move an avatar through it based on gyroscope data, and ends by displaying whether the player won or lost. The code includes functions for generating the maze with walls, drawing it and game elements to the screen, getting input from the controller to determine movement directions, and handling game logic and output.

Uploaded by

api-489665585
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
812 views16 pages

The A-Mazing Race

The document describes a program that generates and navigates a randomly generated maze using gyroscope input from a DualShock controller, with the difficulty of the maze increasing based on a command line argument; it includes functions to generate and draw the maze, move an avatar through it based on gyroscope data, and ends by displaying whether the player won or lost. The code includes functions for generating the maze with walls, drawing it and game elements to the screen, getting input from the controller to determine movement directions, and handling game logic and output.

Uploaded by

api-489665585
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

TITLE

The A-mazing race

LAB # 7
SECTION # B

FULL NAME
Clark Reimers
SUBMISSION DATE:
04/25/18

DATE: 04/25/18
Problem
We are tasked with creating a randomly generated maze that can be more difficult with higher
set levels and we must be able to navigate an avatar through said maze whether it can be completed or
not. We will need dualshocks for this as well as Ncurses

Analysis
We will need to analyze the data from the dualshocks to decide what inputs we are given and
will need to use to interact with the maze. We will also need to decide how to use this data to create a
moving average in order to move the avatar. You must not be able to move through walls and you
should lose if you get into an entrapment you cannot get out of.

Design
We will need several functions and a do while loop to complete this lap. One function will gather
gyroscopic data from the dualshock to be used as a control for the avatar. We will also need a function
to generate the maze and draw the avatar as well as drop it down every few seconds. We will also need
a function to define how the avatar should interact with the maze walls and to define what it takes to
complete the maze.

Testing
Recursion is something that would be nice to use here. Break the big problem up into little
problems and piece them together, I started with drawing the maze and then the avatar. After that I
needed to figure out how to move the avatar through the maze. Once this was all figured out I could at
least see what was happening graphically if I was to run my code so this might it easier to see what
would need to be changed each time I encountered a problem, such as moving through walls and
moving through walls diagonally as well as not being able to lose if the avatar got trapped and seeing
how hard the maze got when the argument vector was changed (this can be noted where figure 1 is
difficulty 3 and figure 2 is difficulty 5) with testing along each new feature that was added.

Comments
See answers to questions at the very bottom
Source Code

/*-----------------------------------------------------------------------------

- SE 185 Lab 07

- Developed for 185-Rursch by T.Tran and K.Wang

- Name: Clark Reimers

- Section: B

- NetID:Creimers

- Date:04/25/18

-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------

- Includes

-----------------------------------------------------------------------------*/

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <ncurses/ncurses.h>

#include <unistd.h>

#include <string.h>

#include <time.h>

/*-----------------------------------------------------------------------------

- Defines

-----------------------------------------------------------------------------*/

/* Mathmatical constants */

#define PI 3.14159
/* Screen geometry

Use NUMROWS and NUMCOLS for the screen height and width (set by system)

MAXIMUMS */

#define NUMROWS 80

#define NUMCOLS 100

/* Character definitions taken from the ASCII table */

#define AVATAR 'A'

#define WALL '*'

#define EMPTY_SPACE ' '

/*parameter definitions*/

#define WAIT_TIME 300

#define TRUE 1

#define FALSE 0

#define UP 0

#define DOWN 1

#define LEFT 2

#define RIGHT 3

#define NONE 4

/* Number of samples taken to form an moving average for the gyroscope data

Feel free to tweak this. */

#define NUM_SAMPLES 10
/*-----------------------------------------------------------------------------

- Static Data

-----------------------------------------------------------------------------*/

/* 2D character array which the maze is mapped into */

char MAZE[NUMCOLS][NUMROWS];

/* PRE: The level of difficulty will be entered on the command line.

You will have to use the argument to the command line to determine how

difficult the maze is (how many maze characters are on the screen).

POST: Generates a random maze structure into MAZE[][]

You will want to use the rand() function and maybe use the output %100. */

void generate_maze(int difficulty);

/* PRE: MAZE[][] has been initialized by generate_maze()

POST: Draws the maze to the screen. You must use the draw_character

function to print to the screen. You cannot use printf in curses. */

void draw_maze(void);

/* PRE: 0 < x < NUMCOLS, 0 < y < NUMROWS, characters are defined above

POST: Draws character use to the screen and position y,x as in a graph

where x is the horizontal axis and y is the vertical axis.

When using the i and j from the maze, you will want to remember that

i (outer loop) is the NUMROWS and corresponds to y, while j is the NUMCOLS

and corresponds to x. */

void draw_character(int x, int y, char use);

/* PRE: -1.0 < x_mag < 1.0

POST: Returns tilt magnitude scaled to -1.0 -> 1.0


You may want to reuse the roll function written in previous labs. */

double calc_roll(double x_mag);

// compute the average of the first num_items of buffer

double m_avg(double buffer[], int num_items);

int close_to(double tolerance, double point, double value);

// Main - Run with './explore.exe -t -a -b' piped into STDIN

void main(int argc, char* argv[]){

int difficulty, ax, ay, moving;

if(argc > 1) {

difficulty = atoi(argv[1]);

else {

printf("Please provide an argument for difficulty\n");

exit(-1);

// setup screen

initscr();

refresh();

// Generate and draw the maze, with initial avatar

generate_maze(difficulty);

draw_maze();

ay = 0;
ax = (NUMCOLS/2)-7;

// Read accelerometer data to get ready for using moving averages.

int g[6];

//avatar x, avatar y : ax, ay

int t;

double x, y, z, m_avg_x, m_avg_y, m_avg_z;

double arr_x[100], arr_y[100], arr_z[100];

// Event loop

char next_char = MAZE[ay][ax];

int alt_y = ay;

int alt_x = ax;

int last_t, first;

char txt[25];

first = TRUE;

do

// Read data, update average

scanf("%d, %lf, %lf, %lf, %d, %d, %d, %d", &t, &x, &y, &z, &g[0], &g[1], &g[2], &g[3] );

if(first == TRUE) {

last_t = t;

first = FALSE;

if(t - last_t >= WAIT_TIME) {

moving = TRUE;
last_t = t;

else {

moving = FALSE;

//averages

m_avg_x = m_avg(arr_x, NUM_SAMPLES);

m_avg_y = m_avg(arr_y, NUM_SAMPLES);

m_avg_z = m_avg(arr_z, NUM_SAMPLES);

int move_dir = NONE;

int valid = TRUE;

if(close_to(0.5, 1, x) == TRUE && ax > 0) {

move_dir = LEFT;

else if(close_to(0.5, -1, x) == TRUE && ax+1 < NUMCOLS) {

move_dir = RIGHT;

if(move_dir == LEFT) {

if(MAZE[ay][ax-1] == '*') {

move_dir = NONE;

else if(move_dir == RIGHT) {


if(MAZE[ay][ax+1] == '*') {

move_dir = NONE;

// Is it time to move? if so, then move avatar

if(moving == TRUE) {

draw_character(alt_x, alt_y, next_char);

draw_character(ax, ay, AVATAR);

//otherwise it's off-screen

if(ay+1 < NUMROWS) {

alt_y = ay;

if(MAZE[ay+1][ax] != '*') {

ay++;

alt_x = ax;

if(move_dir == LEFT) {

ax--;

else if(move_dir == RIGHT) {

ax++;

else {

ax = ax;

}
//no diagonals

if ((y+1 != alt_y && x-1 != alt_x) && ((y-+1 != alt_y && x+1 != alt_x))){

y = alt_y;

next_char = MAZE[alt_y][alt_x];

if(MAZE[alt_y][alt_x-1] == WALL && MAZE[alt_y][alt_x+1] == WALL || MAZE[alt_y-1][alt_x] ==


WALL) {

strcpy(txt, "YOU LOSE!\n");

break;

refresh();

while(ay != NUMROWS -8); // Change this to end game at right time

// Print the win message

if(ay == NUMROWS-8) {

strcpy(txt, "YOU WIN!\n");

endwin();

printf("%s", txt);

}
void generate_maze(int difficulty) {

srand(time(0));

int n, i, h;

for(i=0;i<NUMROWS;i++) {

for(h=0;h<NUMCOLS;h++) {

n = rand() % 100;

if(n < difficulty) {

MAZE[i][h] = WALL;

else {

MAZE[i][h] = EMPTY_SPACE;

void draw_maze(void) {

int i, h, x, y;

for(i=0;i<NUMROWS;i++) {

for(h=0;h<NUMCOLS;h++)

draw_character(h, i, MAZE[i][h]);

refresh();

}
/* PRE: 0 < x < NUMCOLS, 0 < y < NUMROWS, characters are defined above

POST: Draws character use to the screen and position y,x as in a graph

where x is the horizontal axis and y is the vertical axis.

When using the i and j to draw the maze, you will want to remember that

i (outer loop) is the NUMROWS and corresponds to y, while j (the inner loop) is the NUMCOLS

and corresponds to x.

This code places the Avatar and the maze on the screen.

IT WORKS CORRECTLY AS PROVIDED.

PLEASE DO NOT CHANGE THIS FUNCTION. */

void draw_character(int x, int y, char use)

mvaddch(y,x,use);

refresh();

double calc_roll(double x_mag) {

double val;

if(x_mag <= -1) {

val = asin(-PI/2);

} else if(x_mag >= 1) {

val = asin(PI/2);

} else {

val = asin(x_mag);

}
return val;

double m_avg(double buffer[], int num_items) {

double m_avg = 0;

int i;

for(i = 0; i < num_items; i+=1) {

m_avg = (m_avg + buffer[i])/2.0;

return m_avg;

int close_to(double tolerance, double point, double value) {

int close;

if(value > point - tolerance && value < point + tolerance) {

close = TRUE;

} else {

close = FALSE;

return close;

}
Screen Shots

Image 1
Image 2
Answers to Lab 7 questions:

1. Explain the differences between the raw data and the averaged data in your graph for
part A.

The differences between the raw data and the average data is a moving average, this
means that we take an ordered pair, add them together and then divide by number of
samples. This ensures for a smooth moving average. So for an example this means that if
you have a raw data of 1.0002 and 1.025, then your average would be 1.0126 and as
stated before this makes the movement of the avatar smoother.

2. Explain the delay you used to ensure character movement is not erratic.

The delay I used was a delay of 400 milliseconds. This way I can see the movement of the
avatar easily and would be able to react accordingly without the game dragging on forever
and being way too easy. This also helps to give a smoother moving average as the code
can collect more data points before returning an average making it an overall better
experience.

You might also like