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