![]() |
![]() |
![]() |
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
|