Home | | Syllabus | | Assignments | | Documentation

    Solution to Assignment 2


    /*
     * CSCI384, Problem set 2
     * Solution to Alquerque problem
     * October 1, 2003
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <GL/glut.h>
    
    #define PI 3.14159
    
    /*Function prototypes*/
    void myinit(void);
    int pick(int, int);
    void mouse(int, int, int, int);
    void myReshape(int, int);
    void display(void);
    void initPositions(void);
    
    /*Structure to store state of each game position*/
    struct Posit{
    	GLfloat x;	/*x location of position*/
    	GLfloat y;	/*y location of position*/
    	int state;	/*0 for unoccupied, 1 for player 1, 2 for player 2*/
    	int nearNeighbor[8];	/*list of near neighbors*/
    	int farNeighbor[8];		/*list of far neighbors*/
    } position[25];
    
    GLfloat pieceWidth = 10.0;	/*my pieces stay the same size*/
    int source, dest;			/*where mouse was clicked for move*/
    int mouseCount = 0;			/*how many times mouse was clicked*/
    int player = 1;				/*which player's turn is it?*/
    int player1 = 12;			/*number of pieces player 1 has*/
    int player2 = 12;			/*number of pieces player 2 has*/
    
    /*Global variables*/
    GLsizei wh = 500, ww = 500; /*initial window width and height of window*/
    
    void myinit(void)
    {
    	/*OpenGL initialization.  Set viewport and projection window to
    		ww and wh dimensions*/
    	glClearColor(1.0, 1.0, 1.0, 1.0);
    	glColor3f(1.0, 0.0, 0.0);
    	glViewport(0, 0, ww, wh);
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D(0.0, (GLfloat)ww, 0.0, (GLfloat)wh);
    	glMatrixMode(GL_MODELVIEW);
    }
    
    /*Find if mouse clicked within a game piece*/
    int pick(int x, int y){
    	int i;
    	y = wh -y;		/*Convert to units from bottom left*/
    	for (i = 0; i < 25; i ++){	
    		if ((y > position[i].y - pieceWidth/2) && (y < position[i].y + pieceWidth/2) 
    			&& (x > position[i].x - pieceWidth/2) && (x < position[i].x + pieceWidth/2)){
    			return i;
    		}
    	}
    
    	return -1;	/*No piece selected*/
    }
    
    /*Move the piece from source to destination (if allowed) */
    void move(int src, int dst){
    	int i, between, goodMove=0;
    	
    	if (player == position[src].state){	/*Is it this player's turn?*/
    		for (i = 0; i < 8; i ++){
    			/*check if dst is a near neighbor of source and is empty*/
    			if((position[src].nearNeighbor[i] == dst) && (position[dst].state == 0)){
    				goodMove = 1;
    			}else if ((position[src].farNeighbor[i] == dst) 
    				&& (position[dst].state == 0)){	/*Or is it a far neighbor and empty?*/
    				between = position[src].nearNeighbor[i];	/*if far, get between position*/
    				if((position[between].state != position[src].state)
    					&& (position[between].state != 0)){	/*make sure other player's piece is 
    															between src and dst*/
    						goodMove = 1;
    						/*Decrement appropriate player's pieces, and remove piece from between*/
    						if (position[between].state == 1) {
    							player1 -= 1;
    						} else {
    							player2 -= 1;
    						}
    						position[between].state = 0;
    				}
    			}
    		}
    		
    		if (goodMove == 1){	/*if valid move*/
    			/*change turns*/
    			if(player == 1){
    				player = 2;
    			} else {
    				player = 1;
    			}
    			/*Move player from src to dst*/
    			position[dst].state = position[src].state;
    			position[src].state = 0;
    			display();	/*redisplay*/
    			/*If there's a winner, announce it*/
    			if (player1 == 0) {
    				printf("Player 2 wins!\n");
    			} else if (player2 == 0) {
    				printf("Player 1 wins!\n");
    			}
    		} else {
    			printf("You cannot make that move!\n");
    		}
    	
    	}else{
    		printf("Wrong player!\n");
    	}
    	
    }
    
    void mouse(int button, int state, int x, int y){
    	int where;
    	
    	if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
    		/*Find out if mouse clicked on a valid piece*/
    		where = pick(x, y);
    
    		if((where >= 0) && (where < 25)){
    			SysBeep(5);	/*beep if valid*/
    			if (mouseCount == 0){	/*first click*/
    				source = where;
    				mouseCount += 1;
    			} else if (mouseCount == 1) {	/*second click*/
    				dest = where;
    				move(source, dest);	/*check move and move if OK*/
    				mouseCount = 0;	/*reset mouse count*/
    			}
    		}
    	}
    }
    
    /*reset board according to new window width and height*/
    void myReshape(int w, int h){
    	ww = w;
    	wh = h;
    	
    	myinit();			/*reset viewport and clipping window*/
    	glClear(GL_COLOR_BUFFER_BIT);
    	initPositions();	/*new positions of pieces*/
    	display();			/*redisplay*/
    	glFlush();
    }
    
    /*Calculate x and y positions of each board position*/
    void initPositions(void){
    	int i, j;
    	for(i = 0; i< 5; i ++){
    		for(j = 0; j < 5; j++){
    			position[i*5+j].x = ww*(j+1)/6.0;
    			position[i*5+j].y = wh*(i+1)/6.0;
    		}
    	}
    }
    
    /*Initialize arrays of neighbors*/
    void initNeighbors(){
    	int i, j, pos;
    	/*Set all neighbors to -1*/
    	for (i = 0; i < 25; i++){
    		for(j = 0; j < 8; j++){
    			position[i].nearNeighbor[j] = -1;
    			position[i].farNeighbor[j] = -1;
    		}
    	}
    	
    	for (i=0; i < 25; i++) {
    		pos = i + 1;
    		if (pos%5 != 0 ) {	/*All have neighbors to right, except right edge*/
    			position[i].nearNeighbor[0] = i+1;
    			if(pos%5 != 4) {
    				/*all have far neighbors to right, except right 2 edges*/
    				position[i].farNeighbor[0] = i+2;
    			}
    		}
    		if (pos%5 != 1) {
    			/*All have neighbors to left, except left edge*/
    			position[i].nearNeighbor[1] = i-1;
    			if(pos%5 != 2) {
    				position[i].farNeighbor[1] = i-2;
    			}
    		}
    		if (pos < 21) {
    			/*All have neighbors above, except top row*/
    			position[i].nearNeighbor[2] = i+ 5;
    			if(pos < 16) {
    				position[i].farNeighbor[2] = i+10;
    			}
    		}			
    		if (pos > 5) {
    			/*All have neighbors below, except bottom row*/
    			position[i].nearNeighbor[3] = i- 5;
    			if(pos > 10) {
    				position[i].farNeighbor[3] = i-10;
    			}
    		}
    		if (pos%2 != 0){	/*Only odd numbered positions have diagonals*/
    			/*Diagonals up and to right*/
    			if((pos%5 != 0)	&& (pos < 21)){
    				position[i].nearNeighbor[4] = i+ 6;	
    				if((pos%5 != 4) && (pos <16)){
    					position[i].farNeighbor[4] = i+ 12;
    				}
    			}
    			/*Diagonals down and left*/
    			if((pos%5 != 1)	&& (pos > 5)){
    				position[i].nearNeighbor[5] = i- 6;	
    				if((pos%5 != 2) && (pos > 10)){
    					position[i].farNeighbor[5] = i- 12;
    				}
    			}
    			/*Diagonals up and to left*/
    			if((pos%5 != 1)	&& (pos < 21)){
    				position[i].nearNeighbor[6] = i+ 4;	
    				if((pos%5 != 2) && (pos <16)){
    					position[i].farNeighbor[6] = i+ 8;
    				}
    			}
    			/*Diagonals down and to right*/
    			if((pos%5 != 0)	&& (pos > 5)){
    				position[i].nearNeighbor[7] = i- 4;	
    				if((pos%5 != 4) && (pos > 10)){
    					position[i].farNeighbor[7] = i- 8;
    				}
    			}
    		}
    	}
    
    }
    	
    	
    /*Initialize pieces at beginning of the game*/
    void setUpBoard(void){
    	int i;
    	
    	for (i = 0; i < 25; i++){
    		switch(i+1){
    			case 1:
    			case 2:
    			case 6:
    			case 7:
    			case 11:
    			case 12:
    			case 16:
    			case 17:
    			case 18:
    			case 21:
    			case 22:
    			case 23:
    				position[i].state = 1;
    				break;
    			case 3:
    			case 4:
    			case 5:
    			case 8:
    			case 9:
    			case 10:
    			case 14:
    			case 15:
    			case 19:
    			case 20:
    			case 24:
    			case 25:
    				position[i].state = 2;
    				break;
    			case 13:
    				position[i].state = 0;
    		}
    	}
    }
    
    /*Draw a piece at position x, y*/
    void drawBox(GLfloat x, GLfloat y, GLfloat side){
    	glBegin(GL_QUADS);
    		glVertex2f(x - side/2, y - side/2);
    		glVertex2f(x - side/2, y + side/2);
    		glVertex2f(x + side/2, y + side/2);
    		glVertex2f(x + side/2, y - side/2);
    	glEnd();
    }
    
    /*Draw the pieces on the board*/
    void placePieces(void){
    	int i;
    	
    	for (i = 0; i<25; i++){
    		if (position[i].state == 1){	/*If player 1, draw green*/
    			glColor3f(0.0, 1.0, 0.0);
    			drawBox(position[i].x, position[i].y, pieceWidth);
    		} else if (position[i].state == 2){	/*if player 2 draw blue*/
    			glColor3f(0.0, 0.0, 1.0);
    			drawBox(position[i].x, position[i].y, pieceWidth);
    		}
    	}
    }
    
    /*Draw the lines for the board*/	
    void drawBoard(void){
    	int i;
    	glColor3f(1.0, 0.0, 0.0);
    	glBegin(GL_LINES);
    	for (i = 0; i < 5; i++){
    		glVertex2f(ww/6.0, wh*(i+1)/6.0);	/*horizontal lines*/
    		glVertex2f(ww*5.0/6.0, wh*(i+1)/6.0);
    		glVertex2f(ww*(i+1)/6.0, wh/6.0);	/*vertical lines*/
    		glVertex2f(ww*(i+1)/6.0, wh*5.0/6.0);
    	}
    		/*Big diagonals*/
    		glVertex2f(ww/6.0, wh/6.0);
    		glVertex2f(ww*5.0/6.0, wh*5.0/6.0);
    		glVertex2f(ww/6.0, wh*5.0/6.0);
    		glVertex2f(ww*5.0/6.0, ww/6.0);
    	glEnd();
    	
    	/*Diamond in center*/
    	glBegin(GL_LINE_LOOP);
    		glVertex2f(ww/2, wh/6.0);
    		glVertex2f(ww/6.0, wh/2.0);
    		glVertex2f(ww/2, wh*5.0/6.0);
    		glVertex2f(ww*5.0/6.0, wh/2.0);
    	glEnd();
    
    	
    }
    
    /*Function to draw board and pieces*/
    void display(void){
    	glClear(GL_COLOR_BUFFER_BIT);
    	
    	drawBoard();
    	placePieces();	
    
    	glFlush();
    
    }
    
    /*Menus*/
    void right_menu(int id){
    	if(id == 1){	/*if quit, quit*/
    		exit(0);
    	}else if (id == 2) {
    		/*If new game, re-initialize everything*/
    		initPositions();	/*reset x and y positions*/
    		player = 1;			/*green is first*/
    		player1 = 12;		/*each player has 12 pieces*/
    		player2 = 12;
    		mouseCount = 0;		/*No clicks made yet*/
    		setUpBoard();		/*reset pieces on board*/
    		display();			/*redraw the display*/
    	}
    }
    
    /*Set up a menu*/
    void makeMenus(void){
    	
    	glutCreateMenu(right_menu);
    	glutAddMenuEntry("Quit", 1);
    	glutAddMenuEntry("Start New Game", 2);
    	glutAttachMenu(GLUT_RIGHT_BUTTON);
    }
    
    int main(int argc, char** argv)
    {	
    	glutInit(&argc, argv);
    	glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
    	glutInitWindowSize(ww, wh);
    	glutInitWindowPosition(50,50);
    	glutCreateWindow("Alquerque"); 
    	makeMenus();
    	glutDisplayFunc(display); /*Function called on re-display*/
    	glutMouseFunc(mouse);     /*Function called for mouse-event*/
    	glutReshapeFunc(myReshape); /*Function called when window is resized*/
    	myinit();
    	initPositions();	/*Set up x and y positions for board positions*/
    	initNeighbors();	/*Initialize near and far neighbors*/
    	setUpBoard();		/*Set pieces on board*/
    	glutMainLoop();
    	
    	return 0;
    }
    	
    	
    
    	
    

    Home | | Syllabus | | Assignments | | Documentation


    Constance Royden--croyden@mathcs.holycross.edu
    Computer Science 384
    Date Created: August 17, 1999
    Last Modified: October 1, 2003
    Page Expires: August 17, 2004